package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.constant.EsNormalConstant;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.ExcelPartialExportPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.MultiUnitPricePoJo;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.FormDataRepeatDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataListVO;
import com.xbongbong.paas.pojo.vo.FormDataRepeatVO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.PaasFormExplainService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.MathUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.parent.data.FormDataEsService;
import com.xbongbong.parent.parse.data.FormDataDetailAnalysisDataHelp;
import com.xbongbong.parent.parse.data.FormDataLinkDataGetServiceImpl;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.businessdata.pojo.dto.ProductListDataDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.contractproduct.pojo.dto.ContractProductListDTO;
import com.xbongbong.pro.contractproduct.pojo.vo.ContractProductListVO;
import com.xbongbong.pro.detailtab.dto.DetailTabDataGetDTO;
import com.xbongbong.pro.detailtab.pojo.DataDetailTabPojo;
import com.xbongbong.pro.detailtab.pojo.ProductDetailPojo;
import com.xbongbong.pro.detailtab.vo.ProductDetailVO;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.PersonLabelEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PurchaseErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ChildProductDTO;
import com.xbongbong.pro.form.pojo.dto.EsDataDTO;
import com.xbongbong.pro.formdata.pojo.dto.SaasAnalysisDataDTO;
import com.xbongbong.pro.formdata.pojo.vo.FormDataVO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.label.pojo.LabelForDetailUpadatePojo;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.product.pojo.ProductWarehouseSavePojo;
import com.xbongbong.pro.product.pojo.ProductWithSupplierPojo;
import com.xbongbong.pro.product.pojo.ProductWithWarehousePojo;
import com.xbongbong.pro.product.pojo.StockNotifyPojo;
import com.xbongbong.pro.product.pojo.dto.FilterAttrOnOffJXCDTO;
import com.xbongbong.pro.product.pojo.dto.FormatRelativeProductDTO;
import com.xbongbong.pro.product.pojo.dto.ProductDeleteBatchDTO;
import com.xbongbong.pro.product.pojo.dto.ProductEditAttrUpdateDTO;
import com.xbongbong.pro.product.pojo.dto.ProductListDTO;
import com.xbongbong.pro.product.pojo.dto.ProductSearchDTO;
import com.xbongbong.pro.product.pojo.dto.ProductSerialDTO;
import com.xbongbong.pro.product.pojo.dto.ProductStockVerifyDTO;
import com.xbongbong.pro.product.pojo.dto.ProductUpdateBatchDTO;
import com.xbongbong.pro.product.pojo.dto.ProductUpdateDTO;
import com.xbongbong.pro.product.pojo.vo.ChildProductVO;
import com.xbongbong.pro.product.pojo.vo.ProductDeleteBatchVO;
import com.xbongbong.pro.product.pojo.vo.ProductDeletePromptVO;
import com.xbongbong.pro.product.pojo.vo.ProductListVO;
import com.xbongbong.pro.product.pojo.vo.ProductSearchDetailVO;
import com.xbongbong.pro.product.pojo.vo.ProductSearchVO;
import com.xbongbong.pro.product.pojo.vo.ProductSerialVO;
import com.xbongbong.pro.product.pojo.vo.ProductUpdateBatchVO;
import com.xbongbong.pro.purchaseproduct.pojo.dto.PurchaseProductListDTO;
import com.xbongbong.pro.purchaseproduct.pojo.vo.PurchaseProductListVO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.pro.warehouse.pojo.dto.ProductWarehouseMapDTO;
import com.xbongbong.pro.warehouse.pojo.vo.ProductWarehouseMapVO;
import com.xbongbong.pro.weblist.pojo.WaitContractPojo;
import com.xbongbong.product.data.ProductDataService;
import com.xbongbong.saas.analytical.impl.ProductValidateAnalyticalServiceImpl;
import com.xbongbong.saas.annotation.BusinessTypeToServiceAnnotation;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.MultiUnitConstant;
import com.xbongbong.saas.constant.PageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BusinessProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OpportunityProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductCategoryEntity;
import com.xbongbong.saas.domain.entity.ProductSerialBalanceEntity;
import com.xbongbong.saas.domain.entity.ProductStockInfoEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.ProductUnitPriceEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.SpecificationEntity;
import com.xbongbong.saas.domain.entity.SpecificationValueEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.WarehouseOristockProductEntity;
import com.xbongbong.saas.domain.entity.ext.FormatRelativeProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.BusinessTypeToServiceEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.ContractProduceEnum;
import com.xbongbong.saas.enums.DetailTabBusinessProductEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperatePageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.SmartReplenishmentEnum;
import com.xbongbong.saas.enums.business.WaitInstockEnum;
import com.xbongbong.saas.enums.business.WaitOutstockEnum;
import com.xbongbong.saas.enums.business.WaitPurchaseContractEnum;
import com.xbongbong.saas.enums.business.WaitPurchaseProductEnum;
import com.xbongbong.saas.enums.product.ContractProductEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.BatchSeqExplainHelp;
import com.xbongbong.saas.help.FieldAttrHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasAddHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.workflow.WorkflowProductHelp;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.saas.model.OpportunityProductModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PersonLabelModel;
import com.xbongbong.saas.model.ProductCategoryModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductSerialBalanceModel;
import com.xbongbong.saas.model.ProductUnitPriceModel;
import com.xbongbong.saas.model.ProductUserModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.SpecificationValueModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WarehouseOristockProductModel;
import com.xbongbong.saas.service.ContractProductService;
import com.xbongbong.saas.service.FormatSpecialBusinessService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductWarehouseService;
import com.xbongbong.saas.service.PurchaseProductService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WarehouseService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.saas.util.SpecificationUtil;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.saas.enums.RelativeProductEnum.BARCODE;
import static com.xbongbong.saas.enums.RelativeProductEnum.BATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.COST;
import static com.xbongbong.saas.enums.RelativeProductEnum.GUARANTEE_PERIOD;
import static com.xbongbong.saas.enums.RelativeProductEnum.MEMO;
import static com.xbongbong.saas.enums.RelativeProductEnum.NUM;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCE_DATE;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_NO;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_PRICE;
import static com.xbongbong.saas.enums.RelativeProductEnum.SALE_PRODUCT_PRICE;
import static com.xbongbong.saas.enums.RelativeProductEnum.SPECIFICATION;
import static com.xbongbong.saas.enums.RelativeProductEnum.STOCK;
import static com.xbongbong.saas.enums.RelativeProductEnum.SUBTOTAL;
import static com.xbongbong.saas.enums.RelativeProductEnum.UNIT;
import static com.xbongbong.saas.enums.RelativeProductEnum.WAREHOUSE;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;


/**
 * @author Jian.Wang
 * @date 2019-01-28 9:24
 **/
@Service("ProductService")
@BusinessTypeToServiceAnnotation(businessService = BusinessTypeToServiceEnum.PRODUCT)
public class ProductServiceImpl implements ProductService, FormatSpecialBusinessService {

    private static final Logger LOG = LoggerFactory.getLogger(SaasAddHelp.class);

    @Resource
    private ProductModel productModel;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private ProductWarehouseService productWarehouseService;
    @Resource
    private PurchaseProductService purchaseProductService;
    @Resource
    private ContractProductService contractProductService;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainService paasFormExplainService;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private UserModel userModel;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private FieldAttrHelp fieldAttrHelp;
    @Resource
    private ProductUserModel productUserModel;
    @Resource
    private ProductCategoryModel productCategoryModel;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private FormDataDetailAnalysisDataHelp formDataDetailAnalysisDataHelp;
    @Resource
    private FormDataLinkDataGetServiceImpl formDataLinkDataGetServiceImpl;
    @Resource
    private UserHelp userHelp;
    @Resource
    private SpecificationValueModel specificationValueModel;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private ProductSerialBalanceModel productSerialBalanceModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private WarehouseOristockProductModel warehouseOristockProductModel;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private ProductUnitPriceModel productUnitPriceModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private LabelModel labelModel;
    @Resource
    private WorkflowProductHelp workflowProductHelp;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private OpportunityProductModel opportunityProductModel;
    @Resource
    private ProductDataService productDataService;
    @Resource
    private FormDataEsService formDataEsService;

    private static final List<String> productFilterAttrList = Arrays.asList(ProductEnum.WAREHOUSE.getAttr(), ProductEnum.WAREHOUSE_INFO.getAttr(), ProductEnum.STOCK_INFO.getAttr()
            , ProductEnum.STOCK_NOTIFY.getAttr(), ProductEnum.IS_NOTIFY.getAttr(), ProductEnum.SUPPLIER.getAttr(), ProductEnum.ASSOCIATED_INFO.getAttr()
            ,ProductEnum.BATCH_SHELF_LIFE_MANAGEMENT.getAttr(), ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr(), ProductEnum.SHELF_LIFE_DAYS.getAttr(), ProductEnum.EXPIRATION_ALERT_DAYS.getAttr()
            ,ProductEnum.SERIAL_NUMBER_MANAGEMENT.getAttr(), ProductEnum.ENABLE_SERIAL_NUMBER.getAttr());
    private static final List<String> noBatchSeqAttrList = Arrays.asList(ProductEnum.WAREHOUSE.getAttr(), ProductEnum.WAREHOUSE_INFO.getAttr(), ProductEnum.STOCK_INFO.getAttr()
            , ProductEnum.STOCK_NOTIFY.getAttr(), ProductEnum.IS_NOTIFY.getAttr(), ProductEnum.SUPPLIER.getAttr(), ProductEnum.ASSOCIATED_INFO.getAttr());

    private static final List<String> batchAttrList = Arrays.asList(ProductEnum.BATCH_SHELF_LIFE_MANAGEMENT.getAttr(), ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr(), ProductEnum.SHELF_LIFE_DAYS.getAttr(), ProductEnum.EXPIRATION_ALERT_DAYS.getAttr());

    private static final List<String> seqAttrList = Arrays.asList(ProductEnum.SERIAL_NUMBER_MANAGEMENT.getAttr(), ProductEnum.ENABLE_SERIAL_NUMBER.getAttr());

    @Resource
    private ProductValidateAnalyticalServiceImpl productAnalyticalService;
    @Resource
    private PersonLabelModel personLabelModel;

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
      productAnalyticalService.beforeSave(validateDataDTO);
    }

    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存产品负责人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            productUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    @Override
    public void getFormatData(SaasAnalysisDataDTO saasAnalysisDataDTO, JSONObject result) throws XbbException {
        productModel.formatData(saasAnalysisDataDTO, result);
        // 回显分类
        saasUpdateHelp.formatCategoryId4ShowName(result, ProductEnum.CATEGORY_ID.getAttr(), saasAnalysisDataDTO.getCorpid());
    }

    @Override
    public void associateWithSupplier(ProductWithSupplierPojo productWithSupplierPojo) throws XbbException {
        String corpid = productWithSupplierPojo.getCorpid();
        Long productId = productWithSupplierPojo.getProductId();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.PARENT_ID, productId);
        List<SupplierProductEntity> supplierProductList = supplierProductModel.findEntitys(param);

        Map<Long, SupplierProductEntity> supplierMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, SupplierProductEntity> supplierRelationMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<Long> oriSupplierIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<Long> sameSupplierIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (SupplierProductEntity supplierProduct : supplierProductList) {
            oriSupplierIds.add(supplierProduct.getSupplierId());
            sameSupplierIds.add(supplierProduct.getSupplierId());
            supplierMap.put(supplierProduct.getSupplierId(), supplierProduct);
            supplierRelationMap.put(supplierProduct.getProductId() + StringConstant.COMMA + supplierProduct.getSupplierId(), supplierProduct);
        }
        Map<Long, String> supplierNameMap = productWithSupplierPojo.getSupplierNameMap();
        Map<Long, String> cloneSupplierNameMap = (Map<Long, String>)CloneUtil.deepClone(supplierNameMap);
        Set<Long> newSupplierIds = supplierNameMap.keySet();
        sameSupplierIds.retainAll(newSupplierIds);
        oriSupplierIds.removeAll(sameSupplierIds);
        newSupplierIds.removeAll(sameSupplierIds);

        ChildProductVO childProductVO = productWithSupplierPojo.getChildProductVO();
        List<Long> addIdList = childProductVO.getAddIdList();
        List<Long> editIdList = childProductVO.getEditIdList();
        List<ProductEntityExt> existProductList = childProductVO.getExistProductList();
        Map<Long, String> unitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = relativeProductHelp.getGroupBaseUnitMap(corpid);
        if (CollectionsUtil.isNotEmpty(existProductList)) {
            for (ProductEntityExt productEntityExt : existProductList) {
                JSONObject productData = productEntityExt.getData();
                if (Objects.nonNull(productData) && Objects.equals(productData.getLongValue(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), 1L)) {
                    long unitGroupId = productData.getLongValue(ProductEnum.UNIT.getAttr());
                    MultiUnitItemPoJo multiUnitItemPoJo = groupBaseUnitMap.getOrDefault(unitGroupId, new MultiUnitItemPoJo());
                    unitMap.put(productEntityExt.getId(), multiUnitItemPoJo.getBaseValue().toString());
                } else {
                    unitMap.put(productEntityExt.getId(), FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.UNIT.getAttr(), ""));
                }
            }
        }
        // 排序
        int sort = newSupplierIds.size();
        List<SupplierProductEntity> batchAddList = new ArrayList<>();
        SupplierProductEntity supplierProduct;
        for (Long addId : newSupplierIds) {
            if (CollectionsUtil.isNotEmpty(editIdList)) {
                for (Long childId : editIdList) {
                    supplierProduct = new SupplierProductEntity(corpid, addId, cloneSupplierNameMap.getOrDefault(addId, ""), productId, childId, sort, unitMap.getOrDefault(childId, ""));
                    batchAddList.add(supplierProduct);
                }
            }
            if (CollectionsUtil.isNotEmpty(addIdList)) {
                for (Long childId : addIdList) {
                    supplierProduct = new SupplierProductEntity(corpid, addId, cloneSupplierNameMap.getOrDefault(addId, ""), productId, childId, sort, unitMap.getOrDefault(childId, ""));
                    batchAddList.add(supplierProduct);
                }
            }
        }
       // List<SupplierProductEntity> batchUpdateList = new ArrayList<>();
        for (Long editId : sameSupplierIds) {
            if (supplierMap.containsKey(editId)) {
                sort ++;
                if (CollectionsUtil.isNotEmpty(addIdList)) {
                    for (Long childId : addIdList) {
                        supplierProduct = new SupplierProductEntity(corpid, editId, cloneSupplierNameMap.getOrDefault(editId, ""), productId, childId, sort, unitMap.getOrDefault(childId, ""));
                        batchAddList.add(supplierProduct);
                    }
                }
                if (CollectionsUtil.isNotEmpty(editIdList)) {
                    for (Long childId : editIdList) {
                        if (!supplierRelationMap.containsKey(childId + StringConstant.COMMA + editId)) {
                            supplierProduct = new SupplierProductEntity(corpid, editId, cloneSupplierNameMap.getOrDefault(editId, ""), productId, childId, sort, unitMap.getOrDefault(childId, ""));
                            batchAddList.add(supplierProduct);
                        }
                    }
                }
            }
        }
        // 删除子产品与删除的供应商关系
        if (CollectionsUtil.isNotEmpty(oriSupplierIds)) {
            supplierProductModel.deleteByParentIdAndSupplierIdIn(productId, new ArrayList<>(oriSupplierIds), corpid);
        }
       /* if (!batchUpdateList.isEmpty()) {
            supplierProductModel.updateBatch(batchUpdateList, corpid);
        }*/
        if (!batchAddList.isEmpty()) {
            supplierProductModel.batchInsert(batchAddList);
        }


    }

    /**
     *
     * 处理多单位产品单位和价格对不上的情况
     * @param unitItemPoJos
     * @param price
     */
    @Override
    public JSONArray formatMultiPrice(List<UnitItemPoJo> unitItemPoJos, JSONArray price) {
        return productModel.formatMultiPrice(unitItemPoJos, price);
    }



    @Override
    public void formatParentProduct4Save(JSONObject data,String corpid, ProductEntityExt productEntityExt) throws XbbException {
        if (data == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }

        try {
            // 简单规格模式:{"advancedMode":0/false,"specValue":"8G"}
            // 高级规格模式:{"advancedMode":1/true,"specValue":[{"name":"颜色","value":["红色","黄色"]},{"name":"容量","value":["8G","16G"]}]}
            JSONObject specificationObj = null;
            try {
                specificationObj = data.getJSONObject(ProductEnum.SPECIFICATION.getAttr());
            } catch (Exception e) {
                LOG.warn("formatParentProduct4Save.specificationObj", e);
            }
            boolean enableMultiUnit = Objects.equals(data.getIntValue(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE);
            Double minPrice = null;
            if (specificationObj == null) {
                specificationObj = new JSONObject();
                specificationObj.put("advancedMode", false);
                specificationObj.put("specValue", "");
            } else {
                int advancedMode = 0;
                Boolean advancedModeOn = specificationObj.getBoolean("advancedMode");
                if (advancedModeOn != null) {
                    advancedMode = advancedModeOn ? 1 : 0;
                }
                if (Objects.equals(advancedMode,1)){
                    // 多规格的规格和规格值入库
                    if (!Objects.isNull(specificationObj.getJSONArray("specValue"))){
                        JSONArray specValue = specificationObj.getJSONArray("specValue");
                        for (Object o : specValue){
                            String specKey = (String) ((JSONObject)o).get("name");
                            JSONArray specValueArray =(JSONArray) ((JSONObject)o).get("value");
                            for (Object oo : specValueArray){
                                SpecificationValueEntity entity = new SpecificationValueEntity();
                                entity.setSpecificationKey(specKey);
                                entity.setSpecificationValue((String) oo);
                                entity.setCorpid(corpid);
                                specificationValueModel.save(entity);
                            }
                        }
                    }
                    JSONArray specDetails = specificationObj.getJSONArray(ProductConstant.MUTIL_SPEC_DETAILS);
                    for (int i = 0; i < specDetails.size(); i ++) {
                        JSONObject specObj = specDetails.getJSONObject(i);
                        if (enableMultiUnit) {
                            JSONArray priceArr = specObj.getJSONArray(ProductEnum.PRICE.getAttr());
                            if (Objects.nonNull(priceArr) && !priceArr.isEmpty()) {
                                if (i == 0 || priceArr.getJSONObject(0).getDoubleValue(MultiUnitConstant.RATE) < minPrice) {
                                     minPrice = priceArr.getJSONObject(0).getDoubleValue(MultiUnitConstant.RATE);
                                }
                            }
                        } else {
                            if (i == 0 || specObj.getDoubleValue(ProductEnum.PRICE.getAttr()) < minPrice) {
                                minPrice = specObj.getDoubleValue(ProductEnum.PRICE.getAttr());
                            }
                        }
                    }
                } else {
                    if (enableMultiUnit && data.get(ProductEnum.PRICE.getAttr()) instanceof List) {
                        JSONArray priceArr = data.getJSONArray(ProductEnum.PRICE.getAttr());
                        if (Objects.nonNull(priceArr) && !priceArr.isEmpty()) {
                            minPrice = priceArr.getJSONObject(0).getDoubleValue(MultiUnitConstant.RATE);
                        }
                    } else {
                        minPrice = data.getDoubleValue(ProductEnum.PRICE.getAttr());
                    }
                }
            }
            data.put(ProductEnum.PRICE.getAttr(), minPrice);
            int advancedMode = 0;
            //web前端传过来的是boolean值
            Boolean advancedModeOn = specificationObj.getBoolean(ProductConstant.ADVANCED_MODE);
            if (advancedModeOn != null) {
                advancedMode = advancedModeOn ? 1 : 0;
            }
            data.put(ProductEnum.SPECIFICATION.getAttr(), advancedMode);
            data.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "{}");
            // 父产品的父产品id为0
            data.put(ProductEnum.PARENT_ID.getAttr(), 0);
            // 父产品条码为空
            data.put(ProductEnum.BARCODE.getAttr(), "");
            // 父产品data里荣誉一份产品编号
            data.put(ProductEnum.PRODUCT_NO.getAttr(), productEntityExt.getSerialNo());
            // 被裹挟的产品封面图：有图片时第一张图片为封面图；无图片时删除封面图
            JSONArray images = data.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
            if(images != null && images.size() > 0) {
                JSONArray thumbnails = new JSONArray();
                thumbnails.add(images.get(0));
                data.put(ProductEnum.THUMBNAIL.getAttr(), thumbnails);
            } else {
                data.put(ProductEnum.THUMBNAIL.getAttr(), new JSONArray());
                data.put(ProductEnum.PRODUCT_IMGS.getAttr(), new JSONArray());
            }
            // 格式化关联仓库
            saasSaveHelp.formatLinkBusiness4Save(data,ProductEnum.WAREHOUSE.getAttr(),ProductEnum.WAREHOUSE_LINK_TEXT.getAttr(),ProductEnum.WAREHOUSE.getFieldType());
            saasSaveHelp.formatLinkBusiness4Save(data,ProductEnum.SUPPLIER.getAttr(),ProductEnum.SUPPLIER_LINK_TEXT.getAttr(),ProductEnum.SUPPLIER.getFieldType());
        } catch (Exception e) {
            LOG.error("产品保存formatParentProduct4Save", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }

    @Override
    public ChildProductVO saveChildProduct(PaasFormDataEntity paasFormDataEntity, Boolean isJxcUse, Boolean isInsert,Integer costAccuracy) throws XbbException {
        JSONObject data = paasFormDataEntity.getData();
        String corpid = paasFormDataEntity.getCorpid();
        Long parentProductId = paasFormDataEntity.getId();
        boolean enableMultiUnit = Objects.equals(getIntegerOrDefaultFromFormData(data, ProductEnum.ENABLE_MULTI_UNIT.getAttr(), BasicConstant.ZERO), BasicConstant.ONE);
        //简单规格模式:{"advancedMode":0/false,"specValue":"8G"}
        //高级规格模式:{"advancedMode":1/true,"specValue":[{"name":"颜色","value":["红色","黄色"]},{"name":"容量","value":["8G","16G"]}]}
        JSONObject specificationObj = null;
        try {
            specificationObj = data.getJSONObject(ProductEnum.SPECIFICATION.getAttr());
        } catch (Exception e) {
            LOG.warn("saveChildProduct.specificationObj", e);
        }
        if (specificationObj == null) {
            specificationObj = new JSONObject();
            specificationObj.put(ProductConstant.ADVANCED_MODE, false);
            specificationObj.put(ProductConstant.SPEC_VALUE, "");
        }
        String specValue = specificationObj.getString(ProductConstant.SPEC_VALUE);
        Integer advancedMode;
        //web前端传过来的是boolean值
        Boolean advancedModeOn = specificationObj.getBoolean(ProductConstant.ADVANCED_MODE);
        if (advancedModeOn == null) {
            advancedMode = 0;
        } else {
            advancedMode = advancedModeOn ? 1 : 0;
        }
        if (advancedMode.equals(0)) {
            JSONObject tempSpecValueObj = new JSONObject();
            JSONArray valueArray = new JSONArray();
            valueArray.add(StringUtil.filterDoubleQuotes(specValue));
            tempSpecValueObj.put(StringConstant.VALUE, valueArray);

            JSONArray tempSpecValueArray = new JSONArray();
            tempSpecValueArray.add(tempSpecValueObj);
            specValue = tempSpecValueArray.toJSONString();
        }
        JSONArray specValueArray = JSON.parseArray(specValue);
        // TODO 前面已经有更新了，这里为啥还要更新，而且里面是先删除在更新
        updateSpecification(paasFormDataEntity, specValueArray,isInsert);
        ChildProductVO childProductVO;
        if (advancedMode.equals(1)) {
            // 目前高级规格模式只支持在web端新建编辑
            JSONArray childProductArray = JsonHelperUtil.parseArray(specificationObj.getString(ProductConstant.MUTIL_SPEC_DETAILS));
            if (childProductArray == null || childProductArray.isEmpty()) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205006);
            }
            childProductVO = updateChildProduct(paasFormDataEntity, childProductArray, enableMultiUnit,costAccuracy);
        } else {
            // {"规格1":"8G"}
            String childSpecification = StringUtil.filterDoubleQuotes(specificationObj.getString(ProductConstant.SINGLE_SPEC));

            ProductEntityExt childProduct = new ProductEntityExt();
            BeanUtils.copyProperties(paasFormDataEntity, childProduct);
            JSONObject childData = (JSONObject) data.clone();
            if (isInsert) {
                childProduct.setId(null);
                childProduct.setNum(0D);
            } else {
                ChildProductDTO childProductDTO = new ChildProductDTO();
                childProductDTO.setCorpid(corpid);
                childProductDTO.setParentProductId(Collections.singletonList(parentProductId));
                PaasFormDataEsListVO esDataList = getChildProductList(childProductDTO);

                List<PaasFormDataEntityExt> paasFormDataESList = esDataList.getPaasFormDataESList();
                List<ProductEntityExt> originChildProductList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                boolean updateCost = false;
                if (paasFormDataESList.isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
                }
                for (PaasFormDataEntityExt entity : paasFormDataESList) {
                    ProductEntityExt productEntityExt = new ProductEntityExt();
                    BeanUtil.copyProperties(entity, productEntityExt);
                    productEntityExt.setId(entity.getDataId());
                    if (Objects.nonNull(costAccuracy)) {
                        if (Double.compare(Arith.round(entity.getData().getDouble(ProductEnum.COST.getAttr()), costAccuracy), Arith.round(childData.getDouble(ProductEnum.COST.getAttr()), costAccuracy)) != 0) {
                            updateCost = true;
                        }
                    }
                    originChildProductList.add(productEntityExt);
                }
                childProduct.setUpdateCost(updateCost);
                // 如果编辑之前是单规格 编辑之后也是单规格 那么更新原来的子产品
                ProductEntityExt oldChildProduct = originChildProductList.get(0);
                childProduct.setId(oldChildProduct.getId());
                childProduct.setNum(oldChildProduct.getData().getDouble(ProductEnum.STOCK.getAttr()));
                childProduct.setDataId(oldChildProduct.getId());
                childData.put(ProductEnum.STOCK.getAttr(), oldChildProduct.getData().get(ProductEnum.STOCK.getAttr()));
            }

            // 产品条码查重
            String barcode = data.getString(ProductEnum.BARCODE.getAttr());
            if (StringUtil.isNotEmpty(barcode)) {
                Boolean barcodeRepeat = productBarcodeRepeat(barcode, corpid, childProduct.getId());
                if (!barcodeRepeat) {
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205024.getCode(), String.format(ProductErrorCodeEnum.API_ERROR_205024.getMsg(), childSpecification));
                }
            }

            childData.put(ProductEnum.PARENT_ID.getAttr(), parentProductId);
            childData.put(ProductEnum.SPECIFICATION.getAttr(), 0);
            childData.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), childSpecification);
            childData.put(ProductEnum.ENABLE_SKU.getAttr(),1);
            childData.put(ProductEnum.PRODUCT_NO.getAttr(), paasFormDataEntity.getSerialNo());
            // 保存子产品
            childProduct.setData(childData);
            childProduct.setCost(childData.getDouble(ProductEnum.COST.getAttr()));
            childProduct.setTotalCost(Arith.mul(data.getDouble(ProductEnum.STOCK.getAttr()),data.getDouble(ProductEnum.COST.getAttr())));
            JSONArray priceArray = new JSONArray();
            if (enableMultiUnit) {
                //单规格子产品存基础单位的单价
                try {
                    priceArray = childData.getJSONArray(ProductEnum.PRICE.getAttr());
                } catch (Exception e) {
                    LOG.error("产品保存单价解析错误", e);
                }
                if (!priceArray.isEmpty()) {
                    //没给值得默认给0
                    for (int i = 0; i < priceArray.size(); i++) {
                        JSONObject price = (JSONObject) priceArray.get(i);
                        if (StringUtil.isEmpty(price.getString(BasicConstant.RATE))) {
                            price.put(BasicConstant.RATE, 0D);
                        }
                    }
                    JSONObject priceData = (JSONObject) priceArray.get(0);
                    childData.put(ProductEnum.PRICE.getAttr(), priceData.get(BasicConstant.RATE));
                }
            }
            // 子产品不保存子表单
            productModel.saveNoSubForm(childProduct);
            if (isInsert){
                // 单规格智能补货数据入库
                SmartReplenishmentEntity smartReplenishmentEntity = new SmartReplenishmentEntity();
                smartReplenishmentEntity.setCorpid(childProduct.getCorpid());
                // TODO 编辑添加的子产品最低库存
                smartReplenishmentEntity.setMiniNum(0D);
                smartReplenishmentEntity.setStockNum(0D);
                smartReplenishmentEntity.setProductName(childProduct.getData().getString(ProductEnum.NAME.getAttr()));
                smartReplenishmentEntity.setProductNo(childProduct.getSerialNo());
                smartReplenishmentEntity.setPendingInstockNum(0D);
                smartReplenishmentEntity.setWaitOutstockNum(0D);
                smartReplenishmentEntity.setProductId(childProduct.getId());
                smartReplenishmentEntity.setParentProductId(parentProductId);
                smartReplenishmentEntity.setAddTime(DateTimeUtil.getInt());
                smartReplenishmentEntity.setUpdateTime(DateTimeUtil.getInt());
                smartReplenishmentEntity.setDel(0);
                smartReplenishmentModel.insert(smartReplenishmentEntity);
            }
            //多单位需要保存多价格
            if (enableMultiUnit) {
                ProductUnitPriceEntity productUnitPriceEntity= new ProductUnitPriceEntity();
                productUnitPriceEntity.setPrice(priceArray);
                productUnitPriceEntity.setCorpid(corpid);
                productUnitPriceEntity.setUnitGroupId(childData.getLongValue(ProductEnum.UNIT.getAttr()));
                productUnitPriceEntity.setParentId(parentProductId);
                productUnitPriceEntity.setProductId(childProduct.getId());
                if (isInsert) {
                    productUnitPriceEntity.setId(null);
                }else {
                    List<ProductUnitPriceEntity> entitys = productUnitPriceModel.getPriceEntitysByParentId(corpid, parentProductId);
                    if (!entitys.isEmpty()) {
                        productUnitPriceEntity.setId(entitys.get(0).getId());
                    }else {
                        productUnitPriceEntity.setId(null);
                    }
                }
                productUnitPriceModel.save(productUnitPriceEntity);
            }
            childProductVO = new ChildProductVO();
            if (isInsert) {
                childProductVO.setAddIdList(Collections.singletonList(childProduct.getId()));
                childProductVO.setExistProductList(Collections.singletonList(childProduct));
            } else {
                childProductVO.setEditIdList(Collections.singletonList(childProduct.getId()));
                childProductVO.setExistProductList(Collections.singletonList(childProduct));
                // 更新时先要同步更新智能补货表中的产品名称和编号
                Long productId = childProduct.getId();
                SmartReplenishmentEntity entity = smartReplenishmentModel.getByProducId(corpid, productId);
                if (Objects.nonNull(entity)){
                    entity.setProductName(childProduct.getData().getString(ProductEnum.NAME.getAttr()));
                    entity.setProductNo(childProduct.getData().getString(ProductEnum.PRODUCT_NO.getAttr()));
                    entity.setUpdateTime(DateTimeUtil.getInt());
                    smartReplenishmentModel.update(entity);
                }
            }
        }
        return childProductVO;
    }

    @Override
    public void setChildSpecification(List<PaasFormDataEntityExt> paasFormDataESList, String corpid) {
        formDataHelp.setChildSpecification(paasFormDataESList, corpid);
    }

    /**
     * 规格解析
     * @param isSpec 1为多规格 0为单规格
     * @param specStr 数据格式 ： "{\"颜色\":\"原谅绿\",\"尺寸\":\"大\"}"
     * @param specificationLiist 数据库规格 null时表示不需要排序
     * @return 原谅绿/大
     */
    @Override
    public String decodeSpec(String isSpec, String specStr, List<SpecificationEntity> specificationLiist) {
        return formDataHelp.decodeSpec(isSpec, specStr, specificationLiist);
    }

    @Override
    public void formatChildSpecification(List<PaasFormDataEntityExt> paasFormDataESList, String corpid) {
        String specificationAttr = ProductEnum.SPECIFICATION.getAttr();
        String specificationNameAttr = ProductEnum.SPECIFICATION_LINK_TEXT.getAttr();
        String specification;
        for (PaasFormDataEntityExt entityExt : paasFormDataESList){
            JSONObject data = entityExt.getData();
            specification = data.getString(specificationAttr);
            if (specification == null) {
                continue;
            }
            StringBuilder stringBuilder = new StringBuilder();
            if (Objects.equals(specification,"1")){
                JSONObject specifition;
                try {
                    specifition = FastJsonHelper.getJsonObjectOrDefaultFromFormData(data, specificationNameAttr, new JSONObject());
                } catch (XbbException e) {
                    // todo 暂时兼容一点脏数据
                    specifition = new JSONObject();
                }
                if (!Objects.isNull(specifition)){
                    for (Map.Entry entry : specifition.entrySet()){
                        StringUtil.stringBuilderAppendSuffix(stringBuilder,"/",entry.getValue());
                    }
                }
            } else {
                specification = data.getString(specificationNameAttr);
                stringBuilder.append(specification);
            }
            data.put(specificationAttr, stringBuilder.toString());
        }
    }

    @Override
    public void formatChildSpecification4LinkData(List<FormDataVO> paasFormDataESList, String corpid) {
        SpecificationUtil.formatChildSpecification4LinkData(paasFormDataESList, corpid);
    }

    @Override
    public ListAppVO formatWaitProduct(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        String corpid = formDataListDTO.getCorpid();
        List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
        if (paasFormDataESList.isEmpty()) {
            return new ListAppVO();
        }
        Map<Long,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt entityExt : paasFormDataESList){
            stockMap.put(entityExt.getDataId(),entityExt.getData().getDouble(ProductEnum.STOCK.getAttr()));
        }
        Integer isProduce = 0;
        if (Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WAIT_PURCHASE.getCode())){
            isProduce = ContractProduceEnum.WAIT_PURCHASE.getCode();
        }else {
            isProduce = ContractProduceEnum.WAIT_PRODUCE.getCode();
        }
        //在前面已经解析了
//        setChildSpecification(paasFormDataESList, corpid);
        List<Long> dataIdList = new ArrayList<>(paasFormDataESList.size());
        dataIdList.add(-1L);
        paasFormDataESList.forEach(paasFormDataEntityExt -> dataIdList.add(paasFormDataEntityExt.getId()));
        Map<Long,List<Long>> productAndContractIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> lackStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,WaitContractPojo> waitContractPojoMap = saasListHelp.getWaitContractPojoMap(corpid,dataIdList,lackStockMap,isProduce,productAndContractIdMap,stockMap);

        for (PaasFormDataEntityExt product : paasFormDataESList) {
            JSONObject data = product.getData();
            Long id = product.getId();
            List<Long> contractIdList = productAndContractIdMap.get(id);
            if(Objects.isNull(contractIdList) || Objects.equals(contractIdList.size(), 0)){
                continue;
            }
            List<WaitContractPojo> waitContractPojoList = new ArrayList<>();
            for (Long contractId : contractIdList) {
                WaitContractPojo waitContractPojo = waitContractPojoMap.get(contractId);
                if (waitContractPojo != null) {
                    waitContractPojoList.add(waitContractPojo);
                }
            }
            String productName = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.NAME.getAttr(), "");
            JSONArray explains = new JSONArray();
            JSONObject others = new JSONObject();
//            double num = Arith.sub(lackStockMap.get(id),data.getLong(ProductEnum.STOCK.getAttr()));
            double num = lackStockMap.get(id);
            String barcode = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.SPECIFICATION.getAttr(), "");
            JSONArray productImgs = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, ProductEnum.PRODUCT_IMGS.getAttr(), new JSONArray());
            String productImg = productImgs.isEmpty() ? null : productImgs.get(0).toString();
            String serialNo = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.PRODUCT_NO.getAttr(), "");
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, ProductEnum.PRODUCT_NO.getAttrName(), serialNo));
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, ProductEnum.SPECIFICATION.getAttrName(), barcode));
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, I18nMessageUtil.getMessage(I18nStringConstant.OUT_OF_STOCK_NUM), num));

            others.put(ProductEnum.PRODUCT_IMGS.getSaasAttr(), productImg);
            others.put("contractPurchased", waitContractPojoList.size());
            others.put("formId", product.getFormId());
            others.put("menuId", product.getMenuId());
            others.put(StringConstant.BUSINESS_TYPE, XbbRefTypeEnum.PRODUCT.getCode());
            others.put(StringConstant.DATA_ID, id);
            others.put("sourceBusinessType", XbbRefTypeEnum.CONTRACT.getCode());
            appListPojos.add(new AppListPojo(id, productName, explains, null, null, others));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(paasFormDataEsListVO.getPageHelper().getRowsCount());
        return listAppVO;
    }

    @Override
    public ListAppVO formatWaitPurchaseProduct(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        String corpid = formDataListDTO.getCorpid();
        List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
        if (paasFormDataESList.isEmpty()) {
            return new ListAppVO();
        }
        boolean isEnglish = false;
        String locale = formDataListDTO.getLocale();
        if (Objects.equals(locale,"en_US")){
            isEnglish = true;
        }
        Map<Long,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt entityExt : paasFormDataESList){
            stockMap.put(entityExt.getDataId(),entityExt.getData().getDouble(ProductEnum.STOCK.getAttr()));
        }
        Integer isProduce = 0;
        if (Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WAIT_PURCHASE.getCode())){
            isProduce = ContractProduceEnum.WAIT_PURCHASE.getCode();
        }else {
            isProduce = ContractProduceEnum.WAIT_PRODUCE.getCode();
        }
        //在前面已经解析了
//        setChildSpecification(paasFormDataESList, corpid);
        List<Long> dataIdList = new ArrayList<>(paasFormDataESList.size());
        dataIdList.add(-1L);
        paasFormDataESList.forEach(paasFormDataEntityExt -> dataIdList.add(paasFormDataEntityExt.getId()));

        for (PaasFormDataEntityExt product : paasFormDataESList) {
            JSONObject data = product.getData();
            Long id = data.getLong("productId");
            String productName = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.NAME.getSaasAttr(), "");
            String unit = FastJsonHelper.getStringOrDefaultFromFormData(data, ContractProductEnum.UNIT.getAttr(), "");
            JSONArray explains = new JSONArray();
            JSONObject others = new JSONObject();
            double num = data.getDouble("advisePurchaseNum");
            String contractName = FastJsonHelper.getStringOrDefaultFromFormData(data, ContractEnum.NAME.getAttr(), "");
            String barcode = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.SPECIFICATION.getAttr(), "");
            JSONArray productImgs = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, ProductEnum.PRODUCT_IMGS.getAttr(), new JSONArray());
            String productImg = productImgs.isEmpty() ? null : productImgs.get(0).toString();
//            String serialNo = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.PRODUCT_NO.getAttr(), "");
//            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, ProductEnum.PRODUCT_NO.getAttrName(), serialNo));
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, ProductEnum.SPECIFICATION.getAttrName(), barcode));
            if (isEnglish){
                explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, "unit", unit));
            }else {
                explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, "销售单位", unit));
            }
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, ContractEnum.NAME.getAttrName(), contractName));
            explains.add(String.format(StringConstant.APP_LIST_VALUE_SHOW, I18nMessageUtil.getMessage(I18nStringConstant.OUT_OF_STOCK_NUM), num));


            others.put(ProductEnum.PRODUCT_IMGS.getSaasAttr(), productImg);
//            others.put("contractPurchased", waitContractPojoList.size());
            others.put("formId", product.getFormId());
            others.put("menuId", product.getMenuId());
            others.put(StringConstant.BUSINESS_TYPE, XbbRefTypeEnum.PRODUCT.getCode());
            others.put(StringConstant.DATA_ID, id);
            others.put("sourceBusinessType", XbbRefTypeEnum.CONTRACT.getCode());
            others.put("contractId", data.get("contractId"));
            others.put("advisePurchaseNum", data.getDouble("advisePurchaseNum"));
            others.put("stockSearchId", data.get("stockSearchId"));
            appListPojos.add(new AppListPojo(id, productName, explains, null, null, others));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(paasFormDataEsListVO.getPageHelper().getRowsCount());
        return listAppVO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        // 所有产品map
        String corpid = formDataListDTO.getCorpid();
        List<Long> parentIdList = new ArrayList<>();
        Set<Long> childProductSet = new HashSet<>();
        paasFormDataESList.forEach(item -> parentIdList.add(item.getDataId()));
        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(parentIdList);
        packageEnableSKUCond(formDataListDTO,childProductDTO);
        PaasFormDataEsListVO esDataList = getChildProductList(childProductDTO);
        Map<Long, List<SpecificationEntity>> specificationMap = specificationModel.getSpecificationMap(corpid, parentIdList);
        //多单位导出 单价字段值
        String priceText = null;
        for (PaasFormDataEntityExt entityExt : esDataList.getPaasFormDataESList()){
            JSONObject data = entityExt.getData();
            Long parentId = data.getLong(ProductEnum.PARENT_ID.getAttr()) == null ? 0L : data.getLong(ProductEnum.PARENT_ID.getAttr());
            String spec = data.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
            childProductSet.add(entityExt.getId());
            try {
                if (Objects.equals(data.getInteger(ProductEnum.SPECIFICATION.getAttr()),1)) {
                    List<SpecificationEntity> specList = specificationMap.get(parentId);
                    JSONObject specifition = JSONObject.parseObject(spec);
                    JSONObject sortSpecObj = new JSONObject(new LinkedHashMap<>());
                    specifition = Objects.isNull(specifition) ? new JSONObject() : specifition;
                    Map<String, String> specMap = JSONObject.parseObject(specifition.toJSONString(), new TypeReference<Map<String, String>>() {
                    });
                    if (Objects.nonNull(specList)) {
                        for (SpecificationEntity specificationEntity : specList) {
                            if (specMap.containsKey(specificationEntity.getName())) {
                                if (StringUtil.isNotEmpty(specMap.get(specificationEntity.getName()))) {
                                    sortSpecObj.put(specificationEntity.getName(), specMap.get(specificationEntity.getName()));
                                }
                            }
                        }
                    }
                    data.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), sortSpecObj.toJSONString());
                }

            }catch (Exception e){
                LOG.error("decodeSpec json:" + JSONObject.toJSONString(data));
                LOG.error("decodeSpec:",e);
            }
        }
        // 成本字段解释
        FieldAttrEntity costField = new FieldAttrEntity();
        FieldAttrEntity priceField = new FieldAttrEntity();
        FieldAttrEntity stockField = new FieldAttrEntity();
        List<FieldAttrEntity> fieldAttrEntityList = new ArrayList<>();
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            BeanUtil.copyProperties(fieldAttrEntityForImport, fieldAttrEntity);
            fieldAttrEntityList.add(fieldAttrEntity);
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.COST.getAttr())) {
                costField = fieldAttrEntity;
            } else if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.PRICE.getAttr())) {
                priceField = fieldAttrEntity;
            } else if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.STOCK.getAttr())) {
                stockField = fieldAttrEntity;
            }
        }
        esDataList.getPaasFormDataESList().sort(Comparator.comparing(a -> a.getData().getLong(ProductEnum.TEMP_STOCK.getAttr())));
        Map<Long, List<PaasFormDataEntityExt>> childMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //获取父产品下所有子产品
        Map<Long, List<MultiUnitPricePoJo>> priceMapByProductIdSet = productUnitPriceModel.getPriceMapByProductIdSet(corpid, childProductSet);
        for (PaasFormDataEntityExt paasFormDataEntityExt : esDataList.getPaasFormDataESList()) {
            Long parentId = paasFormDataEntityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr());
            //如果是多单位产品 将单价取出来拼进去
            if (Objects.equals(paasFormDataEntityExt.getData().get(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                if (Objects.nonNull(priceMapByProductIdSet) && priceMapByProductIdSet.size() > BasicConstant.ZERO) {
                    if (priceMapByProductIdSet.containsKey(paasFormDataEntityExt.getDataId())){
                        List<MultiUnitPricePoJo> pricePoJoList = priceMapByProductIdSet.get(paasFormDataEntityExt.getDataId());
                        for (int i = 0; i < pricePoJoList.size(); i++) {
                            MultiUnitPricePoJo multiUnitPricePoJo = pricePoJoList.get(i);
                            if (i == 0) {
                                priceText = attrDecimalPrecisionHelper.setDecPrecision(multiUnitPricePoJo.getRate(), priceField.getAccuracy());
                            } else {
                                priceText = priceText + "|" + attrDecimalPrecisionHelper.setDecPrecision(multiUnitPricePoJo.getRate(), priceField.getAccuracy());
                            }
                        }
                    }
                    paasFormDataEntityExt.getData().put(ProductEnum.PRICE.getAttr(), priceText);
                }
            }
            if (childMap.containsKey(parentId)) {
                childMap.get(parentId).add(paasFormDataEntityExt);
            } else {
                List<PaasFormDataEntityExt> childList = new ArrayList<>();
                childList.add(paasFormDataEntityExt);
                childMap.put(parentId, childList);
            }
        }
        Map<Long, List<SupplierProductEntity>> supplierMap = supplierProductModel.getSupplierProductByParentIdIn(corpid, parentIdList, true);
        List<String> fieldList = new ArrayList<>();
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(ParameterConstant.WAREHOUSE_ID));
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("warehouseName"));
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(StringConstant.PARENTID));
        Map<Long, List<ProductWarehouseEntity>> warehouseMap = productWarehouseModel.getWarehouseProductMapByParentIdIn(corpid, parentIdList, fieldList);
        // 协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userTeamService.getUserIdMap(parentIdList, formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);


        List<PaasFormDataEntityExt> allChildList = new ArrayList<>();
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            Long parentId = paasFormDataEntityExt.getDataId();
            List<SupplierProductEntity> supplierProductEntityList = supplierMap.get(parentId);
            Map<Long, String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionUtils.isNotEmpty(supplierProductEntityList)) {
                for (SupplierProductEntity supplierProductEntity : supplierProductEntityList) {
                    supplierNameMap.put(supplierProductEntity.getSupplierId(), supplierProductEntity.getSupplierName());
                }
                StringBuilder sb = new StringBuilder();
                for (Map.Entry<Long, String> entry : supplierNameMap.entrySet()) {
                    sb.append(entry.getValue()).append(StringConstant.COMMA);
                }
                paasFormDataEntityExt.getData().put(ProductEnum.SUPPLIER.getAttr(), sb.substring(0, sb.length() - 1));
            }
            List<ProductWarehouseEntity> warehouseEntityList = warehouseMap.get(parentId);
            Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionUtils.isNotEmpty(warehouseEntityList)) {
                for (ProductWarehouseEntity warehouseEntity : warehouseEntityList) {
                    if (!Objects.equals(warehouseEntity.getWarehouseId(), ProductConstant.ALL_WAREHOUSE_ID)) {
                        warehouseNameMap.put(warehouseEntity.getWarehouseId(), warehouseEntity.getWarehouseName());
                    }
                }
                StringBuilder sb = new StringBuilder();
                for (Map.Entry<Long, String> entry : warehouseNameMap.entrySet()) {
                    sb.append(entry.getValue()).append(StringConstant.COMMA);
                }
                if (sb.length() > 0) {
                    paasFormDataEntityExt.getData().put(ProductEnum.WAREHOUSE.getAttr(), sb.substring(0, sb.length() - 1));
                }
            }
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setExplainList(fieldAttrEntityList);
            boolean isCostFieldNeedHide = false;
            try {
                isCostFieldNeedHide = ExplainUtil.isFieldNeedHide(costField, handlerExplainDTO);
            } catch (Exception e) {
                LOG.error("formatStockSearchExportValue", e);
            }

            boolean isPriceFieldNeedHide = false;
            try {
                isPriceFieldNeedHide = ExplainUtil.isFieldNeedHide(priceField, handlerExplainDTO);
            } catch (Exception e) {
                LOG.error("formatStockSearchExportValue", e);
            }

            boolean isStockFieldNeedHide = false;
            try {
                isStockFieldNeedHide = ExplainUtil.isFieldNeedHide(stockField, handlerExplainDTO);
            } catch (Exception e) {
                LOG.error("formatStockSearchExportValue", e);
            }

            JSONObject formDataObj = paasFormDataEntityExt.getData();
            List<PaasFormDataEntityExt> childList;
            if (childMap.containsKey(paasFormDataEntityExt.getDataId())) {
                childList = childMap.get(paasFormDataEntityExt.getDataId());
            } else {
                continue;
            }
            allChildList.addAll(childList);

            for (PaasFormDataEntityExt childEntity : childList) {
                // data取父产品的，因为自定义字段子产品中没有解析，导出会报错
//                JSONObject cloneDataObj = (JSONObject) CloneUtil.deepClone(formDataObj);
                // 遇到fastJson：default constructor not found问题用fastJson方法替代CloneUtil.deepClone实现深克隆
                JSONObject cloneDataObj = JSON.parseObject(JSON.toJSONString(formDataObj, SerializerFeature.DisableCircularReferenceDetect));
                JSONObject childDataObj = childEntity.getData();
                cloneDataObj.put(ProductEnum.STOCK.getAttr(), childDataObj.get(ProductEnum.STOCK.getAttr()));
                if (!Objects.equals(BasicConstant.ONE, childEntity.getData().get(ProductEnum.ENABLE_MULTI_UNIT.getAttr()))){
                    cloneDataObj.put(ProductEnum.PRICE.getAttr(), attrDecimalPrecisionHelper.setDecPrecision(childDataObj.getDouble(ProductEnum.PRICE.getAttr()), priceField.getAccuracy()));
                }else {
                    cloneDataObj.put(ProductEnum.PRICE.getAttr(), childEntity.getData().get(ProductEnum.PRICE.getAttr()));
                }

                // 查询精度,更新精度
                Integer accuracy = costField.getAccuracy();
                Double cost = childDataObj.getDouble(ProductEnum.COST.getAttr());
                if(Objects.nonNull(accuracy) && Objects.nonNull(cost)) {
                    cloneDataObj.put(ProductEnum.COST.getAttr(),attrDecimalPrecisionHelper.setDecPrecision(cost, accuracy));
                }else{
                    cloneDataObj.put(ProductEnum.COST.getAttr(),cost);
                }

                cloneDataObj.put(ProductEnum.BARCODE.getAttr(), childDataObj.get(ProductEnum.BARCODE.getAttr()));
                cloneDataObj.put(ProductEnum.VISBLE_USER.getAttr(), formDataObj.get(ProductEnum.VISBLE_USER.getAttr()));
                cloneDataObj.put(ProductEnum.VISBLE_DEPT.getAttr(), formDataObj.get(ProductEnum.VISBLE_DEPT.getAttr()));
                String online = Objects.equals(formDataObj.getDouble(ProductEnum.ONLINE.getAttr()), 1D) ? OperateTypeEnum.ONLINE.getName() : OperateTypeEnum.OFFLINE.getName();
                cloneDataObj.put(ProductEnum.ONLINE.getAttr(), online);
                String spec = childDataObj.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                if (StringUtil.isNotEmpty(spec) && Objects.equals(spec, "{}")) {
                    cloneDataObj.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "");
                }
                cloneDataObj.put(ProductEnum.SPECIFICATION.getAttr(), childDataObj.get(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                //cloneDataObj.put(ProductEnum.SUPPLIER.getAttr(), supplierMap.getOrDefault(parentId, ""));
                if (isCostFieldNeedHide) {
                    cloneDataObj.put(ProductEnum.COST.getAttr(), null);
                }
                if (isPriceFieldNeedHide) {
                    cloneDataObj.put(ProductEnum.PRICE.getAttr(), null);
                }
                if (isStockFieldNeedHide) {
                    cloneDataObj.put(ProductEnum.STOCK.getAttr(), null);
                }

                childEntity.setData(cloneDataObj);
            }
        }
        paasFormDataESList.clear();
        paasFormDataESList.addAll(allChildList);
    }

    /**
     * 封装是否仅导出启用规格子产品
     * @param formDataListDTO
     * @param childProductDTO
     */
    private void packageEnableSKUCond(FormDataListDTO formDataListDTO,ChildProductDTO childProductDTO){
        ExcelPartialExportPojo excelPartialExportPojo = formDataListDTO.getExcelPartialExportPojo();
        if (excelPartialExportPojo == null){
            return;
        }
        childProductDTO.setExportEnableSpecifition(excelPartialExportPojo.getExportEnableSpecifition());
    }

    /**
     * 保存产品规格
     *
     * @param entity         产品实体
     * @param specValueArray 规格:[{"name":"颜色","value":["红色","黄色"]},{"name":"容量","value":["8G","16G"]}]
     * @author GuoJun.HU
     * @since 3.14
     * 创建时间 2017/11/13 19:18
     */
    private void updateSpecification(PaasFormDataEntity entity, JSONArray specValueArray, Boolean isInsert) throws XbbException {
        String corpid = entity.getCorpid();
        Long productId = entity.getId();
        // 如果是新建则直接插入
        if (isInsert){
            List<SpecificationEntity> addBatchList = new ArrayList<>();
            for (int i = 0; i < specValueArray.size(); i++) {
                JSONObject specObj = specValueArray.getJSONObject(i);
                String name = specObj.getString(StringConstant.SAAS_LINK_BUSINESS_NAME);
                String value = specObj.getString(StringConstant.VALUE);
                //fix bug20959  修复了在保存产品时过滤双引号而保存规格时没有过滤双引号的操作
                name = StringUtil.filterDoubleQuotes(name);
                value = productModel.filterProductSpecDoubleQuotesWithArray(value);
                SpecificationEntity specification = new SpecificationEntity();
                specification.setCorpid(corpid);
                specification.setProductId(productId);
                specification.setName(name);
                specification.setValue(value);
                specification.setSort(i + 1);
                addBatchList.add(specification);
            }
            if (!addBatchList.isEmpty()) {
                specificationModel.insertBatch(addBatchList);
            }
        }else {
            JSONObject data = entity.getData();
            // 如果是单规格直接更新 多规格更新则需要进行对比移除已有的插入
            if (Objects.nonNull(data)){
                // 1是高级规格，0是单规格,
                Integer integer = data.getJSONObject(ProductEnum.SPECIFICATION.getAttr()).getInteger("advancedMode");
                List<SpecificationEntity> specificationList = specificationModel.getSpecificationList(corpid, productId);
                if (CollectionUtils.isNotEmpty(specificationList)){
                    // 单规格编辑 不用处理规格表 取得data字段中数据
                    if (Objects.equals(integer,BasicConstant.ONE)){
                        // 多规格的对比更新
                        List<String> valueList = new ArrayList<>();
                        // key=规格的name  value=实体数据
                        Map<String,SpecificationEntity> specificationEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        for (SpecificationEntity specificationEntity : specificationList) {
                            String name = specificationEntity.getName();
                            String value = specificationEntity.getValue();
                            valueList.add(value);
                            specificationEntityMap.put(name,specificationEntity);
                        }
                        List<SpecificationEntity> updateList = new ArrayList<>();
                        for (int i = 0; i < specValueArray.size(); i++) {
                            JSONObject specObj = specValueArray.getJSONObject(i);
                            String name = specObj.getString(StringConstant.SAAS_LINK_BUSINESS_NAME);
                            String value = specObj.getString(StringConstant.VALUE);
                            //fix bug20959  修复了在保存产品时过滤双引号而保存规格时没有过滤双引号的操作
                            name = StringUtil.filterDoubleQuotes(name);
                            value = productModel.filterProductSpecDoubleQuotesWithArray(value);
                            // 如果valu变了 则说明新增了规格值 则需要更新之前的规格数据
                            if (!valueList.contains(value)){
                                // 根据name找到数据库对应的实体
                                SpecificationEntity specificationEntity = specificationEntityMap.get(name);
                                if (Objects.nonNull(specificationEntity)){
                                    specificationEntity.setValue(value);
                                    specificationEntity.setUpdateTime(DateTimeUtil.getInt());
                                    updateList.add(specificationEntity);
                                }
                            }
                        }
                        if (CollectionUtils.isNotEmpty(updateList)){
                            specificationModel.updateBatch(updateList,corpid);
                        }
                    }
                }
            }

        }
    }

    /**
     * 更新父产品下的子产品和子产品关联的分仓库存
     *
     * @param paasFormDataEntity 父产品实体
     * @param childProductArray  子产品列表
     * @param enableMultiUnit           是否多单位
     * @author GuoJun.HU
     * @since 3.14
     * 创建时间 2017/11/14 14:14
     */
    private ChildProductVO updateChildProduct(PaasFormDataEntity paasFormDataEntity, JSONArray childProductArray, boolean enableMultiUnit, Integer costAccuracy) throws XbbException {
        String corpid = paasFormDataEntity.getCorpid();
        Long parentProductId = paasFormDataEntity.getId();
        Double cost = paasFormDataEntity.getData().getDouble(ProductEnum.COST.getAttr());

        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(Collections.singletonList(parentProductId));
        PaasFormDataEsListVO esDataList = getChildProductList(childProductDTO);

        List<PaasFormDataEntityExt> originProductList = esDataList.getPaasFormDataESList();
        Map<Long, ProductEntityExt> originProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Long> specMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt productEntity : originProductList) {
            ProductEntityExt productEntityExt = new ProductEntityExt();
            BeanUtil.copyProperties(productEntity, productEntityExt);
            productEntityExt.setId(productEntity.getDataId());
            originProductMap.put(productEntity.getDataId(), productEntityExt);
            String spec = FastJsonHelper.getStringOrDefaultFromFormData(productEntity.getData(), ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "");
            specMap.put(spec, productEntity.getDataId());
        }
        Map<Long, ProductUnitPriceEntity> multiProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<JSONArray> newMultiProductList = new ArrayList<>();
        List<JSONArray> editMultiProductList = new ArrayList<>();
        if (!originProductList.isEmpty()) {
            List<ProductUnitPriceEntity> entitys = productUnitPriceModel.getPriceEntitysByParentId(corpid, parentProductId);
            for (ProductUnitPriceEntity entity : entitys) {
                multiProductMap.put(entity.getProductId(), entity);
            }
        }

//        if (costAccuracy == null) {
//            costAccuracy = AttrDecimalPrecisionHelper.MAX_PRECISION;
//        }
        List<ProductEntityExt> childProductList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> barcodeList = new ArrayList<>();
        for (int i = 0; i< childProductArray.size(); i++){
            JSONObject childProductObj = childProductArray.getJSONObject(i);
            String childProductSpec = childProductObj.getString(ProductConstant.SPEC_TYPE);
            Long childProductId;
            if (childProductObj.containsKey(ProductConstant.CHILD_PRODUCT_ID)) {
                childProductId = StringUtil.StringToLong(childProductObj.getString(ProductConstant.CHILD_PRODUCT_ID), 0L);
            } else {
                childProductId = specMap.get(childProductSpec);
            }
            boolean isAdd = Objects.equals(childProductId, 0L) || Objects.isNull(childProductId);
            childProductSpec = productModel.filterProductSpecDoubleQuotes(childProductSpec);
            String childProductBarcode = childProductObj.getString(ProductConstant.PRODUCT_CODE);
            String childProductNo = StringUtil.trim(Objects.toString(childProductObj.getString(ProductConstant.SPEC_CODE), ""));
            JSONArray childProductImage = childProductObj.getJSONArray(ProductConstant.PRODUCT_IMAGE);
            Double childProductCost = StringUtil.toDouble(childProductObj.getString(ProductEnum.COST.getAttr()), 0d);
            Double childProductPrice = 0d;
            if (enableMultiUnit) {
                //多规格子产品存基础单位的单价
                JSONArray priceArray = new JSONArray();
                try {
                    priceArray = childProductObj.getJSONArray(ProductEnum.PRICE.getAttr());
                } catch (Exception e) {
                    LOG.error("产品保存单价解析错误", e);
                }
                if (Objects.nonNull(priceArray) && !priceArray.isEmpty()) {
                    //没给值得默认给0
                    for (int j = 0; j < priceArray.size(); j++) {
                        JSONObject price = (JSONObject) priceArray.get(j);
                        if (StringUtil.isEmpty(price.getString(BasicConstant.RATE))) {
                            price.put(BasicConstant.RATE, 0D);
                        }
                    }
                    JSONObject priceData = (JSONObject) priceArray.get(0);
                    childProductPrice = priceData.getDoubleValue(BasicConstant.RATE);
                }
                if (isAdd) {
                    newMultiProductList.add(priceArray);
                } else {
                    editMultiProductList.add(priceArray);
                }
            } else {
                childProductPrice = StringUtil.toDouble(childProductObj.getString(ProductEnum.PRICE.getAttr()), 0d);
            }
            Integer enable = StringUtil.toInt(childProductObj.getString(ProductConstant.ENABLE), 0);

            if (Double.compare(childProductPrice, 0) < 0 || Double.compare(childProductCost, 0) < 0) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205021);
            }

            if (StringUtil.isNotEmpty(childProductBarcode)) {
                if (barcodeList.contains(childProductBarcode)) {
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205024.getCode(), String.format(ProductErrorCodeEnum.API_ERROR_205024.getMsg(), childProductSpec));
                }
                barcodeList.add(childProductBarcode);
                // 条码判重
                Boolean barcodeRepeat = productBarcodeRepeat(childProductBarcode, corpid, childProductId);
                if (!barcodeRepeat) {
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205024.getCode(), String.format(ProductErrorCodeEnum.API_ERROR_205024.getMsg(), childProductSpec));
                }
            }

            ProductEntityExt childProduct = new ProductEntityExt();
            PaasFormDataEntity productEntityExt = (PaasFormDataEntity) CloneUtil.deepClone(paasFormDataEntity);
            BeanUtil.copyProperties(productEntityExt, childProduct);
            boolean updateCost = false;
            if (isAdd) {
                childProduct.setId(null);
                childProduct.setOperate(StringConstant.ADD);
                childProduct.setNum(0D);
            } else if (originProductMap.containsKey(childProductId)) {
                ProductEntityExt oldChildProduct = originProductMap.get(childProductId);
                childProduct.setId(oldChildProduct.getId());
                childProduct.setOperate(StringConstant.EDIT);
                childProduct.setNum(oldChildProduct.getData().getDouble(ProductEnum.STOCK.getAttr()));
                originProductMap.remove(childProductId);
                if (Objects.nonNull(costAccuracy)) {
                    if (Double.compare(Arith.round(oldChildProduct.getData().getDouble(ProductEnum.COST.getAttr()), costAccuracy), Arith.round(childProductCost, costAccuracy)) != 0) {
                        updateCost = true;
                    }
                }
            } else {
                continue;
            }
            childProduct.setUpdateCost(updateCost);
            childProduct.setOwnerId(paasFormDataEntity.getOwnerId() == null ? "" : paasFormDataEntity.getOwnerId());
            childProduct.setDepartmentId(paasFormDataEntity.getDepartmentId() == null ? 0L : paasFormDataEntity.getDepartmentId());
            childProduct.setFlowStatus(paasFormDataEntity.getFlowStatus() == null ? FlowStatusEnum.NOT_NEED_APPROVAL.getType() : paasFormDataEntity.getFlowStatus());
            childProduct.setCreatorId(paasFormDataEntity.getCreatorId() == null ? "" : paasFormDataEntity.getCreatorId());
            JSONObject dataList = childProduct.getData();
            dataList.put(ProductEnum.PARENT_ID.getAttr(), parentProductId);
            dataList.put(ProductEnum.SPECIFICATION.getAttr(), 1);
            dataList.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), childProductSpec);
            dataList.put(ProductEnum.PRODUCT_NO.getAttr(), childProductNo);
            dataList.put(ProductEnum.BARCODE.getAttr(), childProductBarcode);
            dataList.put(ProductEnum.COST.getAttr(), childProductCost);
            dataList.put(ProductEnum.PRICE.getAttr(), childProductPrice);
            dataList.put(ProductEnum.ENABLE_SKU.getAttr(),enable);
            dataList.put(ProductEnum.TEMP_STOCK.getAttr(),i);
            dataList.put(ProductEnum.PRODUCT_IMGS.getAttr(), childProductImage != null ? childProductImage : new JSONArray());
            childProduct.setSerialNo(paasFormDataEntity.getSerialNo());
            childProductList.add(childProduct);
        }

        List<ProductEntityExt> addBatchList = new ArrayList<>();
        List<ProductEntityExt> updateBatchList = new ArrayList<>();
        List<Long> deleteIdIn = new ArrayList<>();
        for (ProductEntityExt childProduct : childProductList) {
            switch (childProduct.getOperate()) {
                case "add":
                    childProduct.setCost(childProduct.getData().getDouble(ProductEnum.COST.getAttr()));
                    childProduct.setTotalCost(Arith.mul(childProduct.getData().getDouble(ProductEnum.STOCK.getAttr()),childProduct.getData().getDouble(ProductEnum.COST.getAttr())));
                    addBatchList.add(childProduct);
                    break;
                case "edit":
                    childProduct.setCost(childProduct.getData().getDouble(ProductEnum.COST.getAttr()));
                    childProduct.setTotalCost(Arith.mul(childProduct.getData().getDouble(ProductEnum.STOCK.getAttr()),childProduct.getData().getDouble(ProductEnum.COST.getAttr())));
                    updateBatchList.add(childProduct);
                    break;
                default:
                    break;
            }
        }
        // 批量添加/更新/删除子产品
        if (!addBatchList.isEmpty()) {
            addBatchList.forEach(item -> {
                // 新增子产品时库存数量置0
                item.getData().put(ProductEnum.STOCK.getAttr(),0);
            });
            productModel.insertBatch(addBatchList);
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = new ArrayList<>();
            // 多规格插入智能补货数据
            for (ProductEntityExt productEntityExt : addBatchList) {
                SmartReplenishmentEntity smartReplenishmentEntity = new SmartReplenishmentEntity();
                smartReplenishmentEntity.setCorpid(productEntityExt.getCorpid());
                // TODO 编辑添加的子产品最低库存
                smartReplenishmentEntity.setMiniNum(0D);
                smartReplenishmentEntity.setStockNum(0D);
                smartReplenishmentEntity.setPendingInstockNum(0D);
                smartReplenishmentEntity.setWaitOutstockNum(0D);
                smartReplenishmentEntity.setProductId(productEntityExt.getId());
                smartReplenishmentEntity.setProductName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                smartReplenishmentEntity.setProductNo(productEntityExt.getSerialNo());
                smartReplenishmentEntity.setParentProductId(parentProductId);
                smartReplenishmentEntity.setAddTime(DateTimeUtil.getInt());
                smartReplenishmentEntity.setUpdateTime(DateTimeUtil.getInt());
                smartReplenishmentEntity.setDel(0);
                smartReplenishmentEntityList.add(smartReplenishmentEntity);
            }
            smartReplenishmentModel.insertBatch(smartReplenishmentEntityList);
        }
        if (!updateBatchList.isEmpty()) {
            List<ProductUpdateDTO> productUpdateList = new ArrayList<>();
            updateBatchList.forEach(item -> {
                ProductUpdateDTO productUpdateDTO = new ProductUpdateDTO();
                productUpdateDTO.setId(item.getId());
                // 防止编辑子产品时丢失库存
                item.getData().remove(ProductEnum.STOCK.getAttr());
                productUpdateDTO.setData(item.getData());
                productUpdateList.add(productUpdateDTO);
            });
            List<UpdateDataEntity> updateDataList = new ArrayList<>();
            productUpdateList.forEach((item)->{
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid);
                updateDataEntity.setSerialNo(paasFormDataEntity.getSerialNo());
                updateDataList.add(updateDataEntity);
            });
            if (!updateDataList.isEmpty()) {
                // 子产品的主表数据更新
                productModel.updateBatch(updateDataList, corpid);
            }
            // 如果重新编辑产品的话，子产品的子表单只会被删除，这段代码没用，而且获取子表单，可用父产品查询
//            Runnable runnable = () -> {
//                try {
//
//                    for (ProductEntityExt item : updateBatchList) {
//                        paasFormSubDataModel.transferSubForm(item, IndexTypeEnum.IDX_SAAS_PRODUCT_SUB);
//                        paasFormSubDataModel.updateSubFormData(item, IndexTypeEnum.IDX_SAAS_PRODUCT_SUB);
//                    }
//                } catch (XbbException e) {
//                    LOG.error("删除子产品或删除产品库存报错", e);
//                }
//            };
//            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);

        }
        ChildProductVO childProductVO = new ChildProductVO();
        List<ProductEntityExt> existProductList = new ArrayList<>();
        existProductList.addAll(addBatchList);
        existProductList.addAll(updateBatchList);
        childProductVO.setExistProductList(existProductList);
        List<Long> addIdList = new ArrayList<>();
        if (!addBatchList.isEmpty()) {
            List<ProductUnitPriceEntity> list = new ArrayList<>();
            if (enableMultiUnit) {
                for (int i = 0; i < addBatchList.size(); i++) {
                    ProductEntityExt productEntityExt = addBatchList.get(i);
                    addIdList.add(productEntityExt.getId());
                    ProductUnitPriceEntity productUnitPriceEntity = new ProductUnitPriceEntity();
                    productUnitPriceEntity.setPrice(newMultiProductList.get(i));
                    productUnitPriceEntity.setCorpid(corpid);
                    productUnitPriceEntity.setUnitGroupId(paasFormDataEntity.getData().getLongValue(ProductEnum.UNIT.getAttr()));
                    productUnitPriceEntity.setId(null);
                    productUnitPriceEntity.setParentId(parentProductId);
                    productUnitPriceEntity.setProductId(productEntityExt.getId());
                    list.add(productUnitPriceEntity);
                }
            }else {
                addBatchList.forEach(entity -> addIdList.add(entity.getId()));
            }
            if (!list.isEmpty()) {
                productUnitPriceModel.insertBatch(list);
            }
        }
        childProductVO.setAddIdList(addIdList);
        List<Long> editIdList = new ArrayList<>();
        if (!updateBatchList.isEmpty()) {
            List<ProductUnitPriceEntity> list = new ArrayList<>();
            List<ProductUnitPriceEntity> insertList = new ArrayList<>();
            if (enableMultiUnit) {
                for (int i = 0; i < updateBatchList.size(); i++) {
                    ProductEntityExt productEntityExt = updateBatchList.get(i);
                    editIdList.add(productEntityExt.getId());
                    ProductUnitPriceEntity productUnitPriceEntity = new ProductUnitPriceEntity();
                    productUnitPriceEntity.setCorpid(corpid);
                    productUnitPriceEntity.setParentId(parentProductId);
                    productUnitPriceEntity.setProductId(productEntityExt.getId());
                    productUnitPriceEntity.setUnitGroupId(paasFormDataEntity.getData().getLongValue(ProductEnum.UNIT.getAttr()));
                    ProductUnitPriceEntity priceEntity = multiProductMap.getOrDefault(productEntityExt.getId(), new ProductUnitPriceEntity());
                    productUnitPriceEntity.setId(priceEntity.getId());
                    productUnitPriceEntity.setPrice(editMultiProductList.get(i));
                    if (Objects.isNull(productUnitPriceEntity.getId())) {
                        insertList.add(productUnitPriceEntity);
                    }else {
                        list.add(productUnitPriceEntity);
                    }
                }
            }else {
                updateBatchList.forEach(entity -> editIdList.add(entity.getId()));
            }
            if (!list.isEmpty()) {
                productUnitPriceModel.updateBatch(list, corpid);
            }
            if (!insertList.isEmpty()) {
                productUnitPriceModel.insertBatch(insertList);
            }
        }
        childProductVO.setEditIdList(editIdList);
        childProductVO.setDelIdList(deleteIdIn);
        return childProductVO;
    }

    /**
     * 获取原父产品下的子产品，从es获取
     *
     * @param childProductDTO
     * @author chaoxiong.lei
     * @Date 21:29 2019/2/14
     * @since v1.0
     **/
    @Override
    public PaasFormDataEsListVO getChildProductList(ChildProductDTO childProductDTO) throws XbbException {
        return formDataEsService.getChildProductList(childProductDTO);
    }

    @Override
    public ProductDetailVO getFormatExplainJsonArray(DetailTabDataGetDTO detailTabDataGetDTO, ProductEntityExt product, String corpid) throws XbbException {
        Long productId = product.getId();
        JSONObject dataList = product.getData();
        // 获取父产品下的子产品
        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(Collections.singletonList(productId));
        PaasFormDataEsListVO esDataList = getChildProductList(childProductDTO);
        List<PaasFormDataEntityExt> childProductList = esDataList.getPaasFormDataESList();


        // 获取产品解释
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        List<FieldAttrEntity> fieldAttrEntities = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Map<String, FieldAttrEntity> nowProductExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        FilterAttrOnOffJXCDTO filterAttrOnOffJXCDTO = new FilterAttrOnOffJXCDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, filterAttrOnOffJXCDTO);
        filterAttrOnOffJXCDTO.setFieldAttrEntityList(fieldAttrEntities);
        filterAttrOnOffJXCDTO.setOperatePageCode(OperatePageEnum.DETAIL.getCode());
        productModel.filterAttrOnOffJXC(filterAttrOnOffJXCDTO);
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //协同团队
        userTeamService.getUserIdMap(Collections.singletonList(productId), corpid, XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(detailTabDataGetDTO, handlerExplainDTO);
        handlerExplainDTO.setCreatorId(product.getCreatorId());
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(product.getDataId(), new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(product.getDataId(), new ArrayList<>()));
        handlerExplainDTO.setExplainList(new ArrayList<>(nowProductExplainMap.values()));

        ProductDetailVO productDetailVO = new ProductDetailVO();
        List<ProductDetailPojo> baseInfoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ProductDetailPojo> fileInfoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ProductDetailPojo> imageInfoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 获取自定义字段的值
        dataList = getIsRedundantField(detailTabDataGetDTO, fieldAttrEntities, product);

        List<SupplierProductEntity> supplierProductList = supplierProductModel.getSupplierProductByParentId(corpid, productId);
        Map<Long, String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (SupplierProductEntity supplierProductEntity : supplierProductList) {
            supplierNameMap.put(supplierProductEntity.getSupplierId(), supplierProductEntity.getSupplierName());
        }

        FieldAttrEntity priceField = nowProductExplainMap.getOrDefault(ProductEnum.PRICE.getAttr(), new FieldAttrEntity());
        int priceAccuracy = priceField.getAccuracy() == null ? AttrDecimalPrecisionHelper.DEFAULT_PRECISION : priceField.getAccuracy();


        // 是否是多单位
        boolean enableMultiUnit = Objects.equals(dataList.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE);
        List<PaasFormDataEntityExt> multiProductList = new ArrayList<>();
        Map<Long, Object> multiProductsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (enableMultiUnit) {
            handleMultiPrice(multiProductsMap, multiProductList,corpid, productId, priceAccuracy);
        }

        boolean creatorInVisible = false;
        boolean addTimeInVisible = false;
        boolean updateTimeInVisible = false;
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
            // 产品字段高级不可见
            Boolean invisible = ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO);
            if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CREATORID.getType())) {
                creatorInVisible = invisible;
            }
            if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.ADDTIME.getType())) {
                addTimeInVisible = invisible;
            }
            if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.UPDATETIME.getType())) {
                updateTimeInVisible = invisible;
            }

            // 过滤掉子表单
            if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SEPARATOR.getType())) {
                continue;
            }

            boolean shouldPutToRet = true;
            boolean putToSpecInfoBlock = false;
            String attr = fieldAttrEntity.getAttr();

            ProductDetailPojo productDetailPojo = new ProductDetailPojo(fieldAttrEntity);
            if (Objects.equals(fieldAttrEntity.getVisible(), 0) || invisible || !Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                // 不可见，不返回
                continue;
            }
            // 是否是多规格
            Integer advancedMode = getIntegerOrDefaultFromFormData(dataList, ProductEnum.SPECIFICATION.getAttr(), 0);
            boolean multiSpec = Objects.equals(advancedMode, 1);
            if (fieldAttrEntity.getIsRedundant().equals(0)) {
                if (Objects.equals(attr, ProductEnum.NAME.getAttr())
                        || Objects.equals(attr, ProductEnum.INSTRUCTION.getAttr())
                        || Objects.equals(attr, ProductEnum.SERIALNO.getAttr())) {
                    // 普通处理
                    productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, ""));
                    if ( Objects.equals(attr,ProductEnum.SERIALNO.getAttr())){
                        productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, product.getSerialNo()));
                    }
                } else if (Objects.equals(attr, ProductEnum.BARCODE.getAttr())) {
                    // 单规格详情页显示条码 多规格详情页不显示条码
                    shouldPutToRet = !(multiSpec && childProductList.size() > 1);
                    if (shouldPutToRet && childProductList.size() > 0) {
                        PaasFormDataEntityExt childProduct = childProductList.get(0);
                        JSONObject childData = childProduct.getData();
                        productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(childData, attr, ""));
                    }
                } else if (Objects.equals(attr, ProductEnum.CATEGORY_ID.getAttr())) {
                    Long categoryId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, attr, 0L);
                    ProductCategoryEntity categoryEntity = productCategoryModel.getByKey(categoryId, corpid);
                    String categoryName = Objects.nonNull(categoryEntity) && !Objects.equals(categoryEntity.getDel(), DelEnum.DELETE.getDel()) ? categoryEntity.getName() : "";
                    productDetailPojo.setValue4Show(categoryName);
                } else if (Objects.equals(attr, ProductEnum.SPECIFICATION.getAttr())) {
                    if (multiSpec && childProductList.size() > 1) {
                        List<FieldAttrEntity> explains = new ArrayList<>();
                        FieldAttrEntity costField = nowProductExplainMap.getOrDefault(ProductEnum.COST.getAttr(), new FieldAttrEntity());
                        int costAccuracy = costField.getAccuracy() == null ? AttrDecimalPrecisionHelper.DEFAULT_PRECISION : costField.getAccuracy();
                        //FieldAttrEntity priceField = nowProductExplainMap.getOrDefault(ProductEnum.PRICE.getAttr(), new FieldAttrEntity());
                        //int priceAccuracy = priceField.getAccuracy() == null ? AttrDecimalPrecisionHelper.DEFAULT_PRECISION : priceField.getAccuracy();
                        explains.add(costField);
                        explains.add(priceField);
                        FieldAttrEntity stockField = nowProductExplainMap.getOrDefault(ProductEnum.STOCK.getAttr(), new FieldAttrEntity());
                        FieldAttrEntity barcodeField = nowProductExplainMap.getOrDefault(ProductEnum.BARCODE.getAttr(), new FieldAttrEntity());
                        putToSpecInfoBlock = true;
                        JSONArray childProductArray = new JSONArray();
                        Boolean costInvisible = ExplainUtil.isFieldNeedHide(nowProductExplainMap.get(ProductEnum.COST.getAttr()), handlerExplainDTO);
                        Boolean priceInvisible = ExplainUtil.isFieldNeedHide(nowProductExplainMap.get(ProductEnum.PRICE.getAttr()), handlerExplainDTO);
                        Boolean stockInvisible = ExplainUtil.isFieldNeedHide(nowProductExplainMap.get(ProductEnum.STOCK.getAttr()), handlerExplainDTO);
                        Collections.sort(childProductList , Comparator.comparing(a -> a.getData().getLong(ProductEnum.TEMP_STOCK.getAttr())));
                        for (PaasFormDataEntityExt entity : childProductList) {
                            JSONObject childDataList = entity.getData();
                            JSONObject childProductObj = new JSONObject();
                            JSONObject specObj = JSONObject.parseObject(childDataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                            String productNo = childDataList.getString(ProductEnum.PRODUCT_NO.getAttr());
                            JSONArray productImages = childDataList.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
                            Double cost = childDataList.getDouble(ProductEnum.COST.getAttr());
                            Double stock = childDataList.getDouble(ProductEnum.STOCK.getAttr());
                            Double price = childDataList.getDouble(ProductEnum.PRICE.getAttr());
                            String barcode = childDataList.getString(ProductEnum.BARCODE.getAttr());
                            Integer isUse = childDataList.getInteger(ProductEnum.ENABLE_SKU.getAttr());
                            // 产品库存数量精度
                            stock = attrDecimalPrecisionHelper.setPrecision(stock, stockField.getAccuracy());

                            childProductObj.put("childProductId", entity.getDataId());
                            childProductObj.put("childProductSpec", specObj);
                            childProductObj.put("childProductNo", productNo);
                            childProductObj.put("childProductImage", productImages != null ? productImages : new JSONArray());
                            childProductObj.put("isUse", Objects.equals(isUse, 1));
                            if (!Objects.equals(isUse,1)){
                                continue;
                            }
                            if (costInvisible) {
                                childProductObj.put("childProductCost", StringConstant.INVISIBLE_VALUE);
                            } else {
                                childProductObj.put("childProductCost", new BigDecimal(cost).setScale(costAccuracy, BigDecimal.ROUND_HALF_UP).toPlainString());
                            }
                            if (stockInvisible){
                                childProductObj.put("childProductStock", StringConstant.INVISIBLE_VALUE);
                            }else {
                                childProductObj.put("childProductStock", stock);
                            }
                            if (enableMultiUnit) {
                                childProductObj.put("childProductPrice", multiProductsMap.getOrDefault(entity.getDataId(), new JSONArray()));
                            }else {
                                childProductObj.put("childProductPrice", new BigDecimal(price).setScale(priceAccuracy, BigDecimal.ROUND_HALF_UP).toPlainString());
                            }
                            childProductObj.put("childProductBarcode", barcode == null ? "" : barcode);
                            childProductArray.add(childProductObj);
                        }
                        JSONObject specificationObj = new JSONObject();
                        specificationObj.put("childProductArray", childProductArray);
                        JSONArray specificationArray = specificationModel.getSpecificationArray(corpid, productId);
                        specificationObj.put("advancedSpecification", specificationArray);
                        boolean costShow = Objects.equals(costField.getIsOpen(), 1) && Objects.equals(costField.getVisible(), 1) && !costInvisible;
                        boolean priceShow = Objects.equals(priceField.getIsOpen(), 1) && Objects.equals(priceField.getVisible(), 1) && !priceInvisible;
                        //boolean stockShow = Objects.equals(stockField.getIsOpen(), 1) && Objects.equals(stockField.getVisible(), 1);
                        boolean barcodeShow = Objects.equals(barcodeField.getIsOpen(), 1) && Objects.equals(barcodeField.getVisible(), 1);
                        // 控制字段是否显示
                        JSONObject attrShowObj = new JSONObject();
                        attrShowObj.put("childProductCost", costShow);
                        //attrShowObj.put("childProductStock", stockShow);
                        attrShowObj.put("childProductPrice", priceShow);
                        attrShowObj.put("childProductBarcode", barcodeShow);
                        attrShowObj.put("childProductMultiUnit", enableMultiUnit);
                        attrShowObj.put("childProductImage", true);
                        specificationObj.put("attrShowObj", attrShowObj);
                        productDetailPojo.setValue4Show(specificationObj);
                        productDetailPojo.setExplains(explains);
                    } else {
                        // 如果是多规格的产品但是只有一个子产品或者是单规格产品则显示唯一的子产品规格
                        String childSpecification = "";
                        if (childProductList.size() > 0) {
                            PaasFormDataEntityExt childProduct = childProductList.get(0);
                            JSONObject childData = childProduct.getData();
                            childSpecification = FastJsonHelper.getStringOrDefaultFromFormData(childData, ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "");
                            if (multiSpec) {
                                childSpecification = specificationModel.joinSpecification(childSpecification);
                            }
                        }
                        productDetailPojo.setValue4Show(childSpecification);
                    }
                } else if (Objects.equals(attr, ProductEnum.STOCK.getAttr())) {
                    double stock = 0D;
                    for (PaasFormDataEntityExt entity : childProductList) {
                        JSONObject childData = entity.getData();
                        Double childStock = getDoubleOrDefaultFromFormData(childData, attr, 0D);
                        stock = Arith.add(stock, childStock);
                    }
                    stock = attrDecimalPrecisionHelper.setPrecision(stock, fieldAttrEntity.getAccuracy());
                    productDetailPojo.setValue4Show(stock);
                } else if (Objects.equals(attr, ProductEnum.PRICE.getAttr())) {
                    String priceStr;
                    if (enableMultiUnit) {
                        //多单位产品都需要做价格排序
                        priceStr = getPriceOrCostRegion(multiProductList, attr, fieldAttrEntity.getAccuracy());
                    } else if (multiSpec) {
                        // 将子产品按照价格排序
                        priceStr = getPriceOrCostRegion(childProductList, attr, fieldAttrEntity.getAccuracy());
                    } else {
                        Double price = getDoubleOrDefaultFromFormData(childProductList.get(0).getData(), attr, 0D);
                        priceStr = attrDecimalPrecisionHelper.formatMoneyPrecision(price, fieldAttrEntity);
                    }
                    productDetailPojo.setValue4Show(priceStr);
                } else if (Objects.equals(attr, ProductEnum.COST.getAttr())){
                    String priceStr;
                    if (multiSpec) {
                        // 将子产品按照价格排序
                        priceStr = getPriceOrCostRegion(childProductList, attr, fieldAttrEntity.getAccuracy());
                    } else {
                        Double price = getDoubleOrDefaultFromFormData(childProductList.get(0).getData(), attr, 0D);
                        priceStr = attrDecimalPrecisionHelper.formatMoneyPrecision(price, fieldAttrEntity);
                    }
                    productDetailPojo.setValue4Show(priceStr);
                    if (Objects.equals(attr, ProductEnum.COST.getAttr()) && invisible) {
                        productDetailPojo.setValue4Show(StringConstant.INVISIBLE_VALUE);
                    }
                } else if (Objects.equals(attr, ProductEnum.UNIT.getAttr())) {
                    List<ItemPoJo> productItems = saasFormHelp.getProductItems(corpid);
                    fieldAttrEntity.setItems(productItems);
                    String unitStr = FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, "");
                    String unit = fieldAttrHelp.getDataDictionaryTextByValue(unitStr, fieldAttrEntity);
                    productDetailPojo.setValue4Show(unit);
                } else if (Objects.equals(attr, ProductEnum.SUPPLIER.getAttr())) {
                   StringBuilder stringBuilder = new StringBuilder();
                   for (Map.Entry<Long, String> entry : supplierNameMap.entrySet()) {
                       StringUtil.stringBuilderAppendSuffix(stringBuilder,"/",entry.getValue());
                   }
                   productDetailPojo.setValue4Show(stringBuilder.toString());
                } else if (Objects.equals(attr, ProductEnum.ATTACHMENT.getAttr())) {
                    // 附件
                    String attachment = FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, "");
                    JSONArray jsonArray = FastJsonHelper.parseArray(attachment);
                    JSONArray attachArray = new JSONArray();
                    for (int i=0; i< jsonArray.size(); i++) {
                        String attachItem = jsonArray.getString(i);
                        JSONObject attachItemObj = FastJsonHelper.parseObject(attachItem);
                        if (!attachItemObj.isEmpty()) {
                            attachArray.add(attachItemObj);
                        }
                    }
                    productDetailPojo.setValue4Show(attachArray);
                } else if (Objects.equals(attr, ProductEnum.PRODUCT_IMGS.getAttr())) {
                    // 图片
                    JSONArray imageArray;
                    try {
                        imageArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, attr, new JSONArray());
                    } catch (Exception e) {
                        imageArray = new JSONArray();
                    }
                    productDetailPojo.setValue4Show(imageArray);
                } else if (Objects.equals(attr, ProductEnum.ENABLE_MULTI_UNIT.getAttr())) {
                    if (enableMultiUnit) {
                        productDetailPojo.setValue4Show(OperateTypeEnum.YES.getName());
                    } else {
                        productDetailPojo.setValue4Show(OperateTypeEnum.NO.getName());
                    }
                } else if (Objects.equals(attr, ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr())) {
                    Integer enableBatch = getIntegerOrDefaultFromFormData(dataList, attr, 0);
                    if (BasicConstant.ONE.equals(enableBatch)) {
                        productDetailPojo.setValue4Show(OperateTypeEnum.YES.getName());
                    } else {
                        productDetailPojo.setValue4Show(OperateTypeEnum.NO.getName());
                    }
                } else if (Objects.equals(attr, ProductEnum.SHELF_LIFE_DAYS.getAttr())) {
                    String shelfLifeDays = FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, "");
                    productDetailPojo.setValue4Show(shelfLifeDays);
                } else if (Objects.equals(attr, ProductEnum.EXPIRATION_ALERT_DAYS.getAttr())) {
                    String expirationAlertDays = FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, "");
                    productDetailPojo.setValue4Show(expirationAlertDays);
                } else if (Objects.equals(attr, ProductEnum.ENABLE_SERIAL_NUMBER.getAttr())) {
                    Integer enableSerialNumber = getIntegerOrDefaultFromFormData(dataList, attr, 0);
                    if (BasicConstant.ONE.equals(enableSerialNumber)) {
                        productDetailPojo.setValue4Show(OperateTypeEnum.YES.getName());
                    } else {
                        productDetailPojo.setValue4Show(OperateTypeEnum.NO.getName());
                    }
                } else  if(Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.LABEL.getAttr())){
                    JSONArray jsonArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, attr, new JSONArray());
                    List<LabelForDetailUpadatePojo> pojoList = new ArrayList<>();
                    List<Long> longs = JSON.parseArray(jsonArray.toJSONString(), Long.class);
                    if (!longs.isEmpty()) {
                        List<LabelEntity> labelEntities = labelModel.getByLabelIds(longs,corpid);
                        labelEntities.forEach(item -> {
                            LabelForDetailUpadatePojo labelForDetailUpadatePojo= new LabelForDetailUpadatePojo();
                            labelForDetailUpadatePojo.setId(item.getId());
                            labelForDetailUpadatePojo.setName(item.getName());
                            labelForDetailUpadatePojo.setColor(item.getColor());
                            pojoList.add(labelForDetailUpadatePojo);
                        });
                    }
                    PersonLabelEntity personLabelEntity = personLabelModel.getPersonLabelByRefType(corpid, XbbRefTypeEnum.PRODUCT.getCode(), productId,
                            detailTabDataGetDTO.getUserId() );
                    if (Objects.nonNull(personLabelEntity)) {
                        JSONArray labelNameArray = personLabelEntity.getLabelName();
                        if (labelNameArray !=null && labelNameArray.size() > 0) {
                            for (Object labelName : labelNameArray) {
                                LabelForDetailUpadatePojo labelForDetailUpadatePojo= new LabelForDetailUpadatePojo();
                                labelForDetailUpadatePojo.setId(personLabelEntity.getId());
                                labelForDetailUpadatePojo.setName(labelName.toString());
                                labelForDetailUpadatePojo.setColor(personLabelEntity.getLabelColor());
                                pojoList.add(labelForDetailUpadatePojo);
                            }
                        }
                    }
                    productDetailPojo.setValue4Show(pojoList);
                } else {
                    shouldPutToRet = false;
                }
            } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldAttrEntity.getFieldType())) {
                LinkInfoPojo linkInfoPojo = fieldAttrEntity.getLinkInfo();
                if (dataList.get(attr) instanceof Map) {
                    JSONObject linkData = dataList.getJSONObject(attr);
                    JSONObject data = linkData.getJSONObject(StringConstant.JSON_DATA);
                    DataDetailTabPojo dataDetailTabPojo = new DataDetailTabPojo();
                    dataDetailTabPojo.setAppId(linkInfoPojo.getLinkAppId());
                    dataDetailTabPojo.setMenuId(linkInfoPojo.getLinkMenuId());
                    dataDetailTabPojo.setFormId(linkInfoPojo.getLinkFormId());
                    dataDetailTabPojo.setSaasMark(linkInfoPojo.getLinkSaasMark());
                    dataDetailTabPojo.setBusinessType(linkInfoPojo.getLinkBusinessType());
                    dataDetailTabPojo.setDataId(linkData.getLong(StringConstant.DATA_ID));
                    productDetailPojo.setEntity(dataDetailTabPojo);
                    productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(data, linkInfoPojo.getLinkKey(), ""));
                }
            } else if (Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), fieldAttrEntity.getFieldType())) {
                if (dataList.get(attr) instanceof List) {
                    // [{dataId: 294, data: {serialNo: "WAO.20201021004"}, id: 294},{dataId: 403, data: {serialNo: "WAO.20210816001"}, id: 403}]
                    JSONArray linkDataArray = dataList.getJSONArray(attr);
                    LinkInfoPojo linkInfoPojo = fieldAttrEntity.getLinkInfo();
                    List<ProductDetailPojo> productDetailPojoList = new ArrayList<>();
                    for (int i=0; i<linkDataArray.size(); i++) {
                        // {dataId: 294, data: {serialNo: "WAO.20201021004"}, id: 294}
                        JSONObject linkData = linkDataArray.getJSONObject(i);
                        JSONObject data = linkData.getJSONObject(StringConstant.JSON_DATA);
                        DataDetailTabPojo dataDetailTabPojo = new DataDetailTabPojo();
                        dataDetailTabPojo.setAppId(linkInfoPojo.getLinkAppId());
                        dataDetailTabPojo.setMenuId(linkInfoPojo.getLinkMenuId());
                        dataDetailTabPojo.setFormId(linkInfoPojo.getLinkFormId());
                        dataDetailTabPojo.setSaasMark(linkInfoPojo.getLinkSaasMark());
                        dataDetailTabPojo.setBusinessType(linkInfoPojo.getLinkBusinessType());
                        dataDetailTabPojo.setDataId(linkData.getLong(StringConstant.DATA_ID));
                        ProductDetailPojo productDetailPojoItem = new ProductDetailPojo(fieldAttrEntity);
                        productDetailPojoItem.setEntity(dataDetailTabPojo);
                        productDetailPojoItem.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(data, linkInfoPojo.getLinkKey(), ""));
                        productDetailPojoList.add(productDetailPojoItem);
                    }
                    productDetailPojo.setValue4Show(productDetailPojoList);
                }
            } else if (Objects.equals(FieldTypeEnum.DEPT.getType(), fieldAttrEntity.getFieldType()) || Objects.equals(FieldTypeEnum.USER.getType(), fieldAttrEntity.getFieldType())) {
                if (Objects.nonNull(dataList.get(attr))) {
                    JSONObject jsonObject = dataList.getJSONObject(attr);
                    productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(jsonObject, "name", ""));
                }
            } else if (Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldAttrEntity.getFieldType())
                    || Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldAttrEntity.getFieldType())
                    || Objects.equals(FieldTypeEnum.OWNERID.getType(), fieldAttrEntity.getFieldType())
            ) {
                if (Objects.nonNull(dataList.get(attr))) {
                    JSONArray jsonArray = dataList.getJSONArray(attr);
                    List<String> nameList = new ArrayList<>();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        nameList.add(jsonObject.getString("name"));
                    }
                    productDetailPojo.setValue4Show(StringUtils.join(nameList, "、"));
                }
            } else if (Objects.nonNull(dataList.get(attr)) && Objects.equals(FieldTypeEnum.DATETIME.getType(), fieldAttrEntity.getFieldType())) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fieldAttrEntity.getDateType());
                Date date = new Date(dataList.getLong(attr)*1000L);
                String dateValue = DateUtil.getString(date, simpleDateFormat);
                productDetailPojo.setValue4Show(dateValue);
            } else if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldAttrEntity.getFieldType())) {
                if (Objects.nonNull(dataList.get(attr))) {
                    JSONObject jsonObject = dataList.getJSONObject(attr);
                    String province = jsonObject.getString(BusinessConstant.PROVINCE);
                    String city = jsonObject.getString(BusinessConstant.CITY);
                    String district = jsonObject.getString(BusinessConstant.DISTRICT);
                    String address = jsonObject.getString(BusinessConstant.ADDRESS);
                    productDetailPojo.setValue4Show(province + city + district + address);
                }
            } else if (Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldAttrEntity.getFieldType())) {
                continue;
            } else if (Objects.nonNull(dataList.get(attr)) && Objects.equals(FieldTypeEnum.NUM.getType(), fieldAttrEntity.getFieldType())) {
                Integer accuracy = 0;
                if (!Objects.equals(1, fieldAttrEntity.getIntegerOnly())) {
                    accuracy = fieldAttrEntity.getAccuracy();
                }
                productDetailPojo.setValue4Show(MathUtil.ceil(dataList.get(attr), accuracy));
            }  else {
                // 自定义字段
                // 普通处理
                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.UPLOAD.getType())) {
                    JSONArray attachmentArray;
                    try {
                        attachmentArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, attr, new JSONArray());
                    } catch (Exception e) {
                        attachmentArray = new JSONArray();
                    }
                    productDetailPojo.setValue4Show(attachmentArray);
                } else if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.IMAGE.getType())) {
                    JSONArray imageArray;
                    try {
                        imageArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, attr, new JSONArray());
                    } catch (Exception e) {
                        imageArray = new JSONArray();
                    }
                    productDetailPojo.setValue4Show(imageArray);
                } else  if(Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.LABEL.getType())){
                    JSONArray jsonArrOrDefaultFromFormData = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, attr, new JSONArray());
                    productDetailPojo.setValue4Show(jsonArrOrDefaultFromFormData);
                } else if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.RADIO_GROUP.getType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.COMBO.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.COMBO_CHECK.getType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CHECKBOX_GROUP.getType())){
                    productDetailPojo.setValue4Show(ItemUtil.parseItemPoJoFromFormData2String(dataList, attr, ""));
                } else  {
                    productDetailPojo.setValue4Show(FastJsonHelper.getStringOrDefaultFromFormData(dataList, attr, ""));
                }
            }
            // 初始化一下简介

            if (shouldPutToRet) {
                Integer fieldType = fieldAttrEntity.getFieldType();
                if (Objects.equals(fieldType, FieldTypeEnum.IMAGE.getType())) {
                    imageInfoList.add(productDetailPojo);
                    continue;
                }
                if (Objects.equals(fieldType, FieldTypeEnum.UPLOAD.getType())) {
                    fileInfoList.add(productDetailPojo);
                    continue;
                }
                if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.INSTRUCTION.getAttr()) && Objects.equals(fieldAttrEntity.getVisible(), 1)) {
                    //productDetailVO.setInstructionInfo(productDetailPojo);
                    continue;
                }
                if (putToSpecInfoBlock && Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.SPECIFICATION.getAttr())) {
                    productDetailVO.setSpecificationInfo(productDetailPojo);
                    continue;
                }
                baseInfoList.add(productDetailPojo);
            }
        }

        productDetailVO.setBaseInfo(baseInfoList);
        productDetailVO.setFileInfoArray(fileInfoList);
        productDetailVO.setImageInfoArray(imageInfoList);

        String creatorId = product.getCreatorId();
        UserEntity creator = userModel.getByKey(creatorId, corpid);
        // 其他返回信息
        JSONObject otherInfoObj = new JSONObject();
        otherInfoObj.put("creator", creatorInVisible ? "--" : (creator != null ? creator.getName() : ""));
        otherInfoObj.put("addTime", addTimeInVisible ? "--" : DateTimeUtil.getStringEpochSecond(product.getAddTime(), DateTimeUtil.SDFYMDHM));
        otherInfoObj.put("updateTime", updateTimeInVisible ? "--" : DateTimeUtil.getStringEpochSecond(product.getUpdateTime(), DateTimeUtil.SDFYMDHM));
        productDetailVO.setOtherInfo(otherInfoObj);
        return productDetailVO;
    }

    @Override
    public void handleMultiPrice(Map<Long, Object> multiProductsMap, List<PaasFormDataEntityExt> multiProductList, String corpid, Long productId,int priceAccuracy) throws XbbException {
        ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
        Map<Long, List<UnitItemPoJo>> groupMap = productFieldPojo.getMultiItems().stream().collect(Collectors.toMap(MultiUnitItemPoJo::getValue, MultiUnitItemPoJo::getItemDataPoJoList));

        List<ProductUnitPriceEntity> entitys = productUnitPriceModel.getPriceEntitysByParentId(corpid, productId);
        for (ProductUnitPriceEntity entity : entitys) {
            JSONArray price = entity.getPrice();
            List<UnitItemPoJo> unitItemPoJos = groupMap.get(entity.getUnitGroupId());
            List<MultiUnitPricePoJo> multiUnitPricePoJos = price.toJavaList(MultiUnitPricePoJo.class);
            Map<Long, String> multiUnitNameMap = new HashMap<>();
            unitItemPoJos.forEach(item->multiUnitNameMap.put(item.getValue(), item.getText()));
            for (MultiUnitPricePoJo itemPoJo : multiUnitPricePoJos) {
                String name = multiUnitNameMap.get(itemPoJo.getValue());
                if (Objects.nonNull(name)) {
                    itemPoJo.setText(name);
                }
            }
            price = JSONArray.parseArray(JSON.toJSONString(multiUnitPricePoJos));
            if (unitItemPoJos.size() != price.size()){
                price = formatMultiPrice(unitItemPoJos, price);
            }
            for (int i = 0; i < price.size(); i++) {
                JSONObject child = (JSONObject) price.get(i);
                child.put(BasicConstant.RATE, new BigDecimal(child.getDoubleValue(BasicConstant.RATE)).setScale(priceAccuracy, BigDecimal.ROUND_HALF_UP).toPlainString());
                child.put(ProductEnum.PRICE.getAttr(), child.getDoubleValue(BasicConstant.RATE));
                PaasFormDataEntityExt entityExt = new PaasFormDataEntityExt();
                entityExt.setData(child);
                multiProductList.add(entityExt);
            }
            multiProductsMap.put(entity.getProductId(), price);
        }
    }

    /**
     * 获取自定义字段的数据
     * @param detailTabDataGetDTO
     * @param fieldList
     * @param productEntityExt
     * @throws XbbException
     */
    private JSONObject getIsRedundantField(DetailTabDataGetDTO detailTabDataGetDTO, List<FieldAttrEntity> fieldList, ProductEntityExt productEntityExt) throws XbbException {
        Iterator<FieldAttrEntity> iterator = fieldList.iterator();
        List<FieldAttrEntity> explainList = new ArrayList<>();
        JSONObject dataList = productEntityExt.getData();
        dataList.put(FieldTypeEnum.OWNERID.getAlias(), Collections.singletonList(productEntityExt.getOwnerId()));
        Map<String, FieldAttrEntity> explainMap = new HashMap<>(fieldList.size());
        while (iterator.hasNext()) {
            FieldAttrEntity fieldAttrEntity = iterator.next();
            if (Objects.equals(1, fieldAttrEntity.getIsRedundant())) {
                explainList.add(fieldAttrEntity);
                explainMap.put(fieldAttrEntity.getAttr(), fieldAttrEntity);
            }
        }
        if (!explainList.isEmpty()) {
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(detailTabDataGetDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
            //  获取用户和部门容器 解析paas的特殊数据 end
            ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
            BeanUtil.copyProperties(detailTabDataGetDTO, parseSingleRowDataDTO);
            parseSingleRowDataDTO.setDataJsonObject(dataList);
            parseSingleRowDataDTO.setExplainMap(explainMap);
            parseSingleRowDataDTO.setUserMap(userMap);
            parseSingleRowDataDTO.setDepartmentMap(departmentMap);
            // 解析数据
            ParseSingleRowDataVO parseSingleRowDataVO = formDataDetailAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
            if (Objects.isNull(parseSingleRowDataVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
            }
            LinkResultDataVO linkResultDataVO = parseSingleRowDataVO.getLinkResultDataVO();
            linkResultDataVO = linkResultDataVO == null ? new LinkResultDataVO() : linkResultDataVO;
            linkResultDataVO.setUserMap(userMap);
            linkResultDataVO.setDepartmentMap(departmentMap);
            dataList = parseSingleRowDataVO.getResult();
            if (!linkResultDataVO.getLinkData().isEmpty() && !linkResultDataVO.getLinkDataSet().isEmpty()) {
                linkResultDataVO.setData(dataList);
                linkResultDataVO.setExplainMap(explainMap);
                linkResultDataVO.setExplainList(explainList);
                FormDataGetDTO formDataGetDTO = new FormDataGetDTO();
                BeanUtil.copyProperties(detailTabDataGetDTO, formDataGetDTO);
                dataList = formDataLinkDataGetServiceImpl.formDataLinkDataGet(formDataGetDTO, linkResultDataVO);
            }
        }
        return dataList;
    }

    @Override
    public String getPriceOrCostRegion(List<PaasFormDataEntityExt> childProductList, String attr, Integer accuracy) throws XbbException {
        return productModel.getPriceOrCostRegion(childProductList, attr, accuracy);
    }

    @Override
    public void formatSpecialUpdateExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        PaasFormDataEntityExt dataEntity = formatExplainDTO.getDataEntity();
        boolean advancedMode = false;
        if (dataEntity != null) {
            JSONObject dataList = dataEntity.getData();
            try {
                Integer advancedModeCode = dataList.getInteger(ProductEnum.SPECIFICATION.getAttr());
                advancedMode = Objects.equals(advancedModeCode, 1);
            } catch (Exception e) {
                LOG.error("规格格式错误", e);
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205061);
            }
        }
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            String attr = fieldAttrEntity.getAttr();
            // 高级规格模式下，产品的成本和价格不可见
            boolean isUnVisibleAttr = advancedMode && (Objects.equals(attr, ProductEnum.PRICE.getAttr())
                    || Objects.equals(attr, ProductEnum.COST.getAttr())
                    || Objects.equals(attr, ProductEnum.BARCODE.getAttr()));
            if (isUnVisibleAttr) {
                if (Objects.equals(formatExplainDTO.getEditFormat(),true)){
                    fieldAttrEntity.setVisible(0);
                }
            } else if (!advancedMode && Objects.equals(attr, ProductEnum.COST.getAttr())) {
                // 单规格，成本字段不可编辑
                fieldAttrEntity.setEditable(0);
            } else if (Objects.equals(attr, ProductEnum.SPECIFICATION.getAttr())) {
                // 规格字段在编辑产品时，不允许编辑
                fieldAttrEntity.setEditable(0);
            }
        }
    }

    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        String corpid = formatExplainDTO.getCorpid();
        DepartmentEntity departmentEntity = departmentModel.getByKey(1L, corpid);
        if (Objects.nonNull(departmentEntity)) {
            List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.VISBLE_DEPT.getAttr())) {
                    if (Objects.isNull(fieldAttrEntity.getDefaultAttr()) || CollectionsUtil.isEmpty(fieldAttrEntity.getDefaultAttr().getDefaultList())) {
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.setDeptDefaultAttrPoJo(departmentEntity.getId().toString(), departmentEntity.getName()));
                    }
                }else if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.UNIT.getAttr())) {
                    ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
                    fieldAttrEntity.setMultiItems(productFieldPojo.getMultiItems());
                }
            }
        }
        FilterAttrOnOffJXCDTO filterAttrOnOffJXCDTO = new FilterAttrOnOffJXCDTO();
        BeanUtil.copyProperties(formatExplainDTO, filterAttrOnOffJXCDTO);
        filterAttrOnOffJXCDTO.setFieldAttrEntityList(formatExplainDTO.getExplainList());
        filterAttrOnOffJXCDTO.setOperatePageCode(OperatePageEnum.NEW.getCode());
        productModel.filterAttrOnOffJXC(filterAttrOnOffJXCDTO);
        formatExplainDTO.setExplainList(filterAttrOnOffJXCDTO.getFieldAttrEntityList());
        // 将产品字段按照sort值排序
        //explainList.sort((FieldAttrEntity f1, FieldAttrEntity f2) -> f2.getSort().compareTo(f1.getSort()));
    }

    /**
     * 新建时将仓库信息加入到解释中
     *
     * @param formatExplainDTO 入参
     * @throws XbbException 异常
     * @author Jian.Wang
     * @date 2019-02-18 20:24
     */
    @Override
    public void formatAddWarehouseToExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        String corpid = formatExplainDTO.getCorpid();
        JSONArray warehouseArray = warehouseModel.fillWarehouseArray(corpid);
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            String attr = fieldAttrEntity.getAttr();
            if ((Objects.equals(attr, ProductEnum.STOCK.getAttr()))) {
                SaasParticularAttributePoJo saasParticularAttributePoJo = new SaasParticularAttributePoJo();
                saasParticularAttributePoJo.setWarehouseArray(warehouseArray);
                fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            }
        }
    }



    @Override
    public Map<Long,JSONObject> setProductConditionsSuper(ProductListDataDTO productListDataDTO, List<ConditionsEntityExt> conditionsEntityExtList, ProductFieldPojo stockField) throws XbbException {
        Map<Long,JSONObject> sourceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        String corpid = productListDataDTO.getCorpid();
        Long refId = productListDataDTO.getRefId();
        Integer refType = productListDataDTO.getRefType();
        //Integer sourceBusinessType = productListDataDTO.getSourceBusinessType();
        Integer businessType = productListDataDTO.getBusinessType();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        List<ConditionsEntityExt> conditionsList = new ArrayList<> ();
        Long warehouseId = productListDataDTO.getWarehouseId();
        switch (xbbRefTypeEnum){
            case CONTRACT:
            case SALES_OPPORTUNITY:
            case SUPPLIER:
            case BOM_BILL:
            case ASSEMBLE:
            case WORK_ORDER:
            case WORK_ORDER_V2:
            case PRODUCTION_ORDER:
            case ORI_STOCK:
            case QUOTATION:
            case SPECIAL_GOODS:
            case RECEIPT_ORDER:
                //上架限制
                conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                //sku启用
                conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                break;
            case REFUND:
                //限制产品
                PaasAppEntity paasAppEntity = paasAppModel.getByAlias(XbbRefTypeEnum.JXC.getAlias(), corpid);
                boolean isOpenJxc = false;
                if (Objects.nonNull(paasAppEntity)) {
                    isOpenJxc = paasAppEntity.getEnable() == 1;
                }
                if (isOpenJxc){
                    //开启进销存，合同出库未退产品
                    List<OutstockProductEntity> outstockProductEntityList = formDataValidateProductHelp.searchContractUnRefund(corpid,refId,true, null);
                    List<Object> productIdList = new ArrayList<>();
                    for (OutstockProductEntity item : outstockProductEntityList){
                        productIdList.add(item.getProductId());
                        BusinessProductEntity businessProductEntity = new BusinessProductEntity();
                        businessProductEntity.setPrice(item.getProductPrice());
                        JSONObject json = relativeProductHelp.putProductSourceData(null,null, businessProductEntity, businessType,corpid, stockField);
                        sourceMap.put(item.getProductId(),json);
                    }
                    if (productIdList.isEmpty()){
                        productIdList.add(-1L);
                    }
                    conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    break;
                }else {
                    //关闭进销存，合同未退产品
                    List<ContractProductEntity> contractProductEntityList = formDataValidateProductHelp.searchContractUnRefund(corpid,refId,false, null);
                    List<Object> productIdList = new ArrayList<>();
                    for (ContractProductEntity item : contractProductEntityList){
                        productIdList.add(item.getProductId());
                        BusinessProductEntity businessProductEntity = new BusinessProductEntity();
                        businessProductEntity.setPrice(item.getPrice());
                        JSONObject json = relativeProductHelp.putProductSourceData(null,null, businessProductEntity, businessType, corpid, stockField);
                        sourceMap.put(item.getProductId(),json);
                    }
                    if (productIdList.isEmpty()){
                        productIdList.add(-1L);
                    }
                    conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    break;
                }
            case PURCHASE:
                //可能限制供应商
                boolean strongAssociation = false;
                FormConfigEntity formConfigEntity = formConfigModel.getEntityByFormId(corpid, productListDataDTO.getFormId(), FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfig());
                if (Objects.isNull(formConfigEntity)){
                    strongAssociation = Objects.equals(FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfigValue(),BasicConstant.IS_USE.toString());
                } else if (Objects.equals(formConfigEntity.getConfigValue(), BasicConstant.IS_USE.toString())) {
                    strongAssociation = true;
                }
                if (strongAssociation) {
                    Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    map.put("corpid",corpid);
                    map.put("supplierId",refId);
                    map.put("del",0);
                    List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.findEntitys(map);
                    List<Object> productIdList = new ArrayList<>();
                    supplierProductEntityList.forEach(item -> productIdList.add(item.getProductId()));
                    if (productIdList.isEmpty()){
                        productIdList.add(-1L);
                    }
                    conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                } else {
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                }
                //上架限制
                conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                break;
            case RETURNED_PURCHASE:
                //限制产品
                List<BusinessProductEntity> businessProductEntities = formDataValidateProductHelp.searchPurchaseUnRefund(corpid, refId);
                for (BusinessProductEntity entity : businessProductEntities){
                    JSONObject json = relativeProductHelp.putProductSourceData(null,null, entity, businessType, corpid, stockField);
                    sourceMap.put(entity.getProductId(),json);
                }
                List<Object> productIdList = new ArrayList<>();
                businessProductEntities.forEach(item -> productIdList.add(item.getProductId()));
                if (productIdList.isEmpty()){
                    productIdList.add(-1L);
                }
                conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                break;
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
                if (Objects.nonNull(refId)){
                    if (Objects.isNull(refType)){
                        refType = InstockTypeEnum.getByStockBusinessType(productListDataDTO.getBusinessType()).getCode();
                    }
                    List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnInstockProduct(corpid,refId,refType, false);
                    for (BusinessProductEntity entity : businessProductEntityList){
                        JSONObject json = relativeProductHelp.putProductSourceData(null,null, entity, businessType, corpid, stockField);
                        sourceMap.put(entity.getProductId(),json);
                    }
                    productIdList = new ArrayList<>();
                    businessProductEntityList.forEach(item -> productIdList.add(item.getProductId()));
                    if (productIdList.isEmpty()){
                        productIdList.add(-1L);
                    }
                    conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                }
                break;
            case INSTOCK:
            case OTHER_INSTOCK:
                if (Objects.nonNull(refId)){
                    if (Objects.isNull(refType)){
                        refType = InstockTypeEnum.getByStockBusinessType(productListDataDTO.getBusinessType()).getCode();
                    }
                    if (Objects.equals(refType,InstockTypeEnum.TRANSFER_INSTOCK.getCode()) || Objects.equals(refType,InstockTypeEnum.INVENTORY_INSTOCK.getCode())){
                        List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnInstockProduct(corpid,refId,refType,false);
                        for (BusinessProductEntity entity : businessProductEntityList){
                            Long guaranteePeriod = entity.getGuaranteePeriod();
                            entity.setGuaranteePeriod(Objects.isNull(guaranteePeriod) ? null : guaranteePeriod * 86400);
                            entity.setSurplusNum(entity.getProductNum());
                            JSONObject json = relativeProductHelp.putProductSourceData(null,null, entity, businessType, corpid, stockField);
                            sourceMap.put(entity.getProductId(),json);
                        }
                        productIdList = new ArrayList<>();
                        businessProductEntityList.forEach(item -> productIdList.add(item.getProductId()));
                        if (productIdList.isEmpty()){
                            productIdList.add(-1L);
                        }
                        conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),productIdList));
                    } else {
                        //上架限制
                        conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                        //sku启用
                        conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    }
                }else {
                    //上架限制
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                }
                break;
            case CONTRACT_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
                if (Objects.nonNull(refId)) {
                    if (Objects.isNull(refType)){
                        refType = OutstockTypeEnum.getByStockBusinessType(productListDataDTO.getBusinessType()).getCode();
                    }
                    List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnOutstockProduct(corpid, refId, refType, false);
                    for (BusinessProductEntity entity : businessProductEntityList){
                        JSONObject json = relativeProductHelp.putProductSourceData(null,null, entity, businessType, corpid, stockField);
                        sourceMap.put(entity.getProductId(),json);
                    }
                    productIdList = new ArrayList<>();
                    if (productIdList.isEmpty()){
                        productIdList.add(-1L);
                    }
                    businessProductEntityList.forEach(item -> productIdList.add(item.getProductId()));
                    conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(), "", FieldTypeEnum.DATAID.getType(), ConditionEnum.IN.getSymbol(), productIdList));
                }
                break;
            case OUTSTOCK:
            case OTHER_OUTSTOCK:
                if (Objects.nonNull(refId)) {
                    if (Objects.isNull(refType)){
                        refType = OutstockTypeEnum.getByStockBusinessType(productListDataDTO.getBusinessType()).getCode();
                    }
                    if (Objects.equals(refType,OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode()) || Objects.equals(refType,OutstockTypeEnum.INVENTORY_OUTSTOCK.getCode())){
                        List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnOutstockProduct(corpid, refId, refType, false);
                        for (BusinessProductEntity entity : businessProductEntityList){
                            Long guaranteePeriod = entity.getGuaranteePeriod();
                            entity.setGuaranteePeriod(Objects.isNull(guaranteePeriod) ? null : guaranteePeriod * 86400);
                            JSONObject json = relativeProductHelp.putProductSourceData(null,null, entity, businessType, corpid, stockField);
                            sourceMap.put(entity.getProductId(),json);
                        }
                        productIdList = new ArrayList<>();
                        productIdList.add(-1L);
                        businessProductEntityList.forEach(item -> productIdList.add(item.getProductId()));
                        conditionsList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(), "", FieldTypeEnum.DATAID.getType(), ConditionEnum.IN.getSymbol(), productIdList));
                    }else {
                        //上架限制
                        conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                        //sku启用
                        conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    }
                }else {
                    //上架限制
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ONLINE.getAttr(),"",ProductEnum.ONLINE.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                    //sku启用
                    conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                }
                break;
            case INVENTORY:
            case TRANSFER:
                //sku启用
                conditionsList.add(new ConditionsEntityExt(ProductEnum.ENABLE_SKU.getAttr(),"",ProductEnum.ENABLE_SKU.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(1)));
                break;
            default:
                break;
        }
        if (Objects.nonNull(warehouseId) && !Objects.equals(businessType, XbbRefTypeEnum.INVENTORY.getCode())){
            //限制仓库、产品
            conditionsList.add(new ConditionsEntityExt(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID),"",FieldTypeEnum.WAREHOUSE_ID.getType(),ConditionEnum.IN.getSymbol(),Collections.singletonList(warehouseId)));
            conditionsList.add(new ConditionsEntityExt(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED),"",FieldTypeEnum.WAREHOUSE_CHECKED.getType(),ConditionEnum.IN.getSymbol(),Collections.singletonList(1)));
        }
        conditionsEntityExtList.addAll(conditionsList);
        return sourceMap;
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProductDeleteBatchVO deleteBatch(ProductDeleteBatchDTO productDeleteBatchDTO) throws XbbException {
        ProductDeleteBatchVO productDeleteBatchVO = new ProductDeleteBatchVO();
        try {
            String corpid = productDeleteBatchDTO.getCorpid();
            List<Long> idIn = productDeleteBatchDTO.getDataIdList();

            BoolQueryBuilder boolQueryBuilder = boolQuery();
            String esData = StringConstant.JSON_DATA + StringConstant.POINT;
            boolQueryBuilder.filter(termsQuery(esData+ProductEnum.PARENT_ID.getAttr(), idIn));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID+StringConstant.POINT+StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            fieldList.add(StringConstant.JSON_DATA);
            List<PaasFormDataEntityExt> childProductESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(childProductESList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            Map<Long, ProductEntityExt> childProductMap = new HashMap<>(childProductESList.size());
            List<Long> parentProductIdList = new ArrayList<>();
            childProductESList.forEach(childProduct -> {
                ProductEntityExt productEntityExt = new ProductEntityExt();
                BeanUtil.copyProperties(childProduct, productEntityExt);
                childProductMap.put(childProduct.getDataId(), productEntityExt);
                parentProductIdList.add(childProduct.getData().getLongValue(ProductEnum.PARENT_ID.getAttr()));
            });
            List<Long> childIdIn = new ArrayList<>(childProductMap.keySet());
            productDeleteBatchDTO.setDataIdList(childIdIn);

            // 判断关联库存，如果有关联库存 不能删除
//            getAssociatedInventoryList(productDeleteBatchDTO, childProductMap);
            // 判断采购合同
            getPurchaseProductList(productDeleteBatchDTO, childProductMap);
            // 判断合同
            getContractProductList(productDeleteBatchDTO, childProductMap);
            // 出入库期初校验
            checkStockDoc(productDeleteBatchDTO, childProductMap);
            // 判断销售机会
            checkOpportunityProduct(productDeleteBatchDTO,childProductMap);
            //查询产品名称 产品列表删除父产品
            Map<String, String> productNoAndName= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            BoolQueryBuilder productBuilder = boolQuery();
            // 添加corpid,formId,del
            productBuilder.filter(termQuery("corpid.keyword", corpid));
            productBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            productBuilder.filter(termsQuery(StringConstant.DATA_ID, parentProductIdList));
            List<String> field = new ArrayList<>();
            field.add(StringConstant.DATA_ID);
            field.add(StringConstant.FORM_ID);
            field.add(ProductEnum.getAttrConnectData(ProductEnum.PRODUCT_NO));
            field.add(ProductEnum.getAttrConnectData(ProductEnum.NAME));
            List<PaasFormDataEntityExt> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, productBuilder, PaasFormDataEntityExt.class, field);
            for(PaasFormDataEntityExt product : productList){
                JSONObject data = product.getData();
                String productNo = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.PRODUCT_NO.getAttr(), "");
                String name = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.NAME.getAttr(), "");
                productNoAndName.put(productNo, name);
            }

            // 删除父产品
            if(!parentProductIdList.isEmpty()) {
                if(BasicConstant.ONE.equals(productDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(parentProductIdList.size())){
                    productModel.deleteByKey(parentProductIdList.get(0),corpid);
                }else {
                    productModel.deleteBatch(parentProductIdList, corpid, DelEnum.DELETE.getDel());
                }
            }

            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termsQuery(esData+ProductEnum.PARENT_ID.getAttr(), parentProductIdList));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID+StringConstant.POINT+StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<String> childProductFieldList = new ArrayList<>();
            childProductFieldList.add(StringConstant.DATA_ID);
            List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, childProductFieldList);
            if(Objects.isNull(childProductList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            if (!childProductList.isEmpty()) {
                List<Long> childProductIdList = new ArrayList<>();
                childProductList.forEach((item)->{
                   childProductIdList.add(item.getDataId());
                });
                if (!childProductIdList.isEmpty()) {
                    //删除子产品和产品库存可异步
                    Runnable runnable = () -> {
                        try {
                            // 删除子产品
                            productModel.deleteBatch(childProductIdList, corpid, DelEnum.DELETE.getDel());
                            // 删除产品库存
                            productWarehouseService.deleteByProductIdIn(corpid, childProductIdList);
                            // 删除供应商产品
                            supplierProductModel.deleteByProductIdIn(childProductIdList, corpid);
                        } catch (XbbException e) {
                            LOG.error("删除子产品或删除产品库存报错", e);
                        }
                    };
                   threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
                }
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = productDeleteBatchDTO.getUserId();
            String userName = productDeleteBatchDTO.getLoginUserName();
            List<String> list = new ArrayList<>();
            Iterator<String> iterator = productNoAndName.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                String value = productNoAndName.get(key);
                if(StringUtil.isEmpty(value)){
                    list.add(key);
                } else {
                    StringBuilder sb = new StringBuilder();
                    sb.append(value).append("（").append(key).append("）");
                    list.add(sb.toString());
                }
            }
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, productDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            String nameStr = StringUtils.join(list, "，");
            if(parentProductIdList.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.PRODUCT.getName(), parentProductIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(ProductEnum.PRODUCT_NO.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.PRODUCT, operateTypeEnum,
                        "", "", memo, productDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(parentProductIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.PRODUCT.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PRODUCT, operateTypeEnum,
                        parentProductIdList.get(0).toString(), nameStr, memo, productDeleteBatchDTO.getHttpHeader());
            }
            productDeleteBatchVO.setDeleteIds(parentProductIdList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productServiceImpl.deleteBatch 批量删除产品报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productDeleteBatchVO;
    }

    private void checkOpportunityProduct(ProductDeleteBatchDTO productDeleteBatchDTO, Map<Long, ProductEntityExt> childProductMap) throws XbbException{
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,productDeleteBatchDTO.getCorpid());
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("productIdIn",productDeleteBatchDTO.getDataIdList());
        param.put("columns","product_id");
        param.put("pageSize",1);
        List<OpportunityProductEntity> opportunityProductEntities=opportunityProductModel.findEntitys(param);
        if (!opportunityProductEntities.isEmpty()) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205115,String.format(ProductErrorCodeEnum.API_ERROR_205115.getMsg(),childProductMap.get(opportunityProductEntities.get(0).getProductId()).getData().getString(ProductEnum.NAME.getAttr())));
        }
    }

    private void checkStockDoc(ProductDeleteBatchDTO productDeleteBatchDTO, Map<Long, ProductEntityExt> childProductMap) throws XbbException {
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,productDeleteBatchDTO.getCorpid());
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("productIdIn",productDeleteBatchDTO.getDataIdList());
        param.put("columns","product_id");
        param.put("pageSize",1);
        List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(param);
        if (!instockProductEntityList.isEmpty()) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205064,String.format(ProductErrorCodeEnum.API_ERROR_205064.getMsg(),childProductMap.get(instockProductEntityList.get(0).getProductId()).getData().getString(ProductEnum.NAME.getAttr())));
        }
        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
        if (!outstockProductEntityList.isEmpty()) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205065,String.format(ProductErrorCodeEnum.API_ERROR_205065.getMsg(),childProductMap.get(outstockProductEntityList.get(0).getProductId()).getData().getString(ProductEnum.NAME.getAttr())));
        }
        List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
        if (!warehouseOristockProductEntityList.isEmpty()) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205066,String.format(ProductErrorCodeEnum.API_ERROR_205066.getMsg(),childProductMap.get(warehouseOristockProductEntityList.get(0).getProductId()).getData().getString(ProductEnum.NAME.getAttr())));
        }
    }

    @Override
    public ProductListVO findProductList(ProductListDTO productListDTO) throws XbbException {
        ProductListVO productListVO =new ProductListVO();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(productListDTO, true);
            List<ProductEntityExt> productList = productModel.findEntitys(param);
            if (Objects.isNull(productList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            productListVO.setProductList(productList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productServiceImpl.findProductList 获取产品报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productListVO;
    }

    /**
     * 获取产品合同关联信息
     * @author 吴峰
     * @date 2019/2/27 21:45
     * @param productDeleteBatchDTO
     * @param productMap
     * @return void
     * @throws XbbException 业务异常
     */
    private void getContractProductList(ProductDeleteBatchDTO productDeleteBatchDTO, Map<Long, ProductEntityExt> productMap) throws XbbException {
        try {
            List<Long> idIn = productDeleteBatchDTO.getDataIdList();
            ContractProductListDTO contractProductListDTO = new ContractProductListDTO();
            BeanUtil.copyProperties(productDeleteBatchDTO, contractProductListDTO);
            if (Objects.nonNull(idIn) && !idIn.isEmpty()) {
                contractProductListDTO.setProductIdList(idIn);
                ContractProductListVO contractProductListVO = contractProductService.findContractProductList(contractProductListDTO);
                if (Objects.isNull(contractProductListVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                if(!contractProductListVO.getContractProductList().isEmpty()) {
                    List<ProductDeletePromptVO> productDeletePromptList = new ArrayList<>();
                    contractProductListVO.getContractProductList().forEach((item)->{
                        ProductEntityExt productEntityExt = productMap.get(item.getProductId());
                        if (Objects.nonNull(productEntityExt) && Objects.nonNull(productEntityExt.getData())) {
                            ProductDeletePromptVO productDeletePromptVO = new ProductDeletePromptVO();
                            productDeletePromptVO.setName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                            productDeletePromptList.add(productDeletePromptVO);
                        }
                    });
                    // 如果有合同 不能删除
                    if(!productDeletePromptList.isEmpty()) {
                        // TODO 是否需要拼装提示信息
                        ProductDeleteBatchVO productDeleteBatchVO = new ProductDeleteBatchVO();
                        productDeleteBatchVO.setProductDeletePromptList(productDeletePromptList);
                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205009);
                    }
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productServiceImpl.getContractProductList 判断合同报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public ProductUpdateBatchVO updateBatch(ProductUpdateBatchDTO productUpdateBatchDTO) throws XbbException {
        ProductUpdateBatchVO productUpdateBatchVO = new ProductUpdateBatchVO();
        try {
            String corpid = productUpdateBatchDTO.getCorpid();
           List<ProductUpdateDTO> productUpdateList = productUpdateBatchDTO.getProductList();
           List<UpdateDataEntity> valueList = new ArrayList<>();
            productUpdateList.forEach((item)->{
                valueList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
            });
            if(!valueList.isEmpty()) {
                productModel.updateBatch(valueList, corpid);
            }
        } catch (Exception e) {
            LOG.error("productServiceImpl.updateBatch 判断合同报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productUpdateBatchVO;
    }


    /**
     * 判断是否有采购合同
     * @author 吴峰
     * @date 2019/2/27 21:34
     * @param productDeleteBatchDTO
     * @param productMap
     * @return void
     * @throws XbbException 业务异常
     */
    private void getPurchaseProductList(ProductDeleteBatchDTO productDeleteBatchDTO, Map<Long, ProductEntityExt> productMap) throws XbbException {
        try {
            List<Long> idIn = productDeleteBatchDTO.getDataIdList();
            PurchaseProductListDTO purchaseProductListDTO = new PurchaseProductListDTO();
            BeanUtil.copyProperties(productDeleteBatchDTO, purchaseProductListDTO);
            if (Objects.nonNull(idIn) && !idIn.isEmpty()) {
                purchaseProductListDTO.setProductIdList(idIn);
                PurchaseProductListVO purchaseProductListVO = purchaseProductService.findPurchaseProduct(purchaseProductListDTO);
                if (Objects.isNull(purchaseProductListVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                if(!purchaseProductListVO.getPurchaseProductList().isEmpty()) {
                    LOG.info("purchaseProduct：：：："+ JSON.toJSONString(purchaseProductListVO.getPurchaseProductList()));
                    List<ProductDeletePromptVO> productDeletePromptList = new ArrayList<>();
                    purchaseProductListVO.getPurchaseProductList().forEach((item)->{
                        ProductEntityExt productEntityExt = productMap.get(item.getProductId());
                        if (Objects.nonNull(productEntityExt) && Objects.nonNull(productEntityExt.getData())) {
                            ProductDeletePromptVO productDeletePromptVO = new ProductDeletePromptVO();
                            productDeletePromptVO.setName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                            productDeletePromptList.add(productDeletePromptVO);
                        }
                    });
                    // 如果有采购合同 不能删除
                    if(!productDeletePromptList.isEmpty()) {
                        // TODO 是否需要拼装提示信息
                        ProductDeleteBatchVO productDeleteBatchVO = new ProductDeleteBatchVO();
                        productDeleteBatchVO.setProductDeletePromptList(productDeletePromptList);
                        throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225020);
                    }
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productServiceImpl.getPurchaseProductList判断采购合同报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }



    /**
     * 产品条码唯一性校验
     * @param childProductBarcode 产品条码
     * @param corpid 公司id
     * @param childProductId 数据id
     * @return true:没有重复，false：有重复
     * @throws XbbException
     */
    public Boolean productBarcodeRepeat(String childProductBarcode, String corpid, Long childProductId) throws XbbException{
        if (childProductBarcode == null || corpid == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        if (childProductId == null) {
            childProductId = 0L;
        }
        // 二维码判重
        FormDataRepeatDTO formDataRepeatDTO = new FormDataRepeatDTO();
        formDataRepeatDTO.setAttr(ProductEnum.BARCODE.getAttr());
        formDataRepeatDTO.setValue(childProductBarcode);
        formDataRepeatDTO.setBusinessType(XbbRefTypeEnum.PRODUCT.getCode());
        formDataRepeatDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        formDataRepeatDTO.setCorpid(corpid);
        // 拼接条件，父产品id不为0
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(ProductEnum.PARENT_ID.getAttr());
        conditionsEntityExt.setSymbol(ConditionEnum.NOEQUAL.getSymbol());
        conditionsEntityExt.setValue(Arrays.asList(0));
        conditionsEntityExt.setFieldType(FieldTypeEnum.NUM.getType());
        FormDataRepeatVO uniqueByBarcode = saasSaveHelp.isUniqueByConditions(formDataRepeatDTO, Arrays.asList(conditionsEntityExt));
        List<PaasFormDataEntityExt> formDataList = uniqueByBarcode.getFormDataList();

        if (formDataList.size() > 1) {
            return false;
        } else {
            if (!formDataList.isEmpty()) {
                PaasFormDataEntityExt paasFormDataEsEntity = formDataList.get(0);
                Long dataId = paasFormDataEsEntity.getDataId();
                if (!Objects.equals(dataId, childProductId)) {
                    return false;
                }
            }
        }
        return true;
    }


    @Override
    public void batchEditAttr(ProductEditAttrUpdateDTO productEditAttrUpdateDTO) throws XbbException {
        try {
            List<Long> idIn = productEditAttrUpdateDTO.getDataIdList();
            String corpid = productEditAttrUpdateDTO.getCorpid();
            Boolean isFieldDependence = productEditAttrUpdateDTO.getIsFieldDependence();

            AttrValuePojo singleAttrValuePojo = ProSaveHelp.getSingleAttrValuePojo(isFieldDependence, productEditAttrUpdateDTO.getFieldEditedList());
            if (Objects.equals(ProductEnum.UNIT.getAttr(), singleAttrValuePojo.getAttr())) {
                if (StringUtil.isDigital(singleAttrValuePojo.getAttr()) && Long.parseLong(singleAttrValuePojo.getAttr()) > ProductConstant.MAX_SINGLE_UNIT_VALUE) {
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205108);
                }
            }
            Map<String, Object> param = BeanUtil.convertBean2Map(productEditAttrUpdateDTO, true);
            param.put("idIn", idIn);
            List<ProductEntityExt> productList = productModel.findEntitys(param);
            if (Objects.isNull(productList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            // 产品没有流程，所以这里不处理审批后能否编辑
            List<ProductUpdateDTO> productUpdateList = new ArrayList<>();
            idIn.forEach((item)->{
                ProductUpdateDTO productUpdateDTO = new ProductUpdateDTO();
                productUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(productEditAttrUpdateDTO.getFieldEditedList());
                productUpdateDTO.setData(data);
                productUpdateList.add(productUpdateDTO);
            });

            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            fieldList.add(StringConstant.JSON_DATA);
            List<PaasFormDataEntityExt> productChildList = findByScroll(idIn, corpid, fieldList);
            //产品除了修改父产品字段，还要修改子产品字段
            Map<Long, Object> parentProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            for (ProductEntityExt productEntityExt : productList) {
                JSONObject data = productEntityExt.getData();
                if (Objects.equals(ProductEnum.UNIT.getAttr(), singleAttrValuePojo.getAttr())
                        && Objects.equals(data.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)) {
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205108);
                }
                parentProductMap.put(productEntityExt.getId(), singleAttrValuePojo.getValue());
            }

            if (Objects.nonNull(productChildList) && !productChildList.isEmpty()) {
                productChildList.forEach((item)-> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.getLong(ProductEnum.PARENT_ID.getAttr()))
                            && parentProductMap.containsKey(data.getLong(ProductEnum.PARENT_ID.getAttr()))) {
                        ProductUpdateDTO productUpdateDTO = new ProductUpdateDTO();
                        productUpdateDTO.setId(item.getDataId());
                        JSONObject updateData = new JSONObject();
                        updateData.put(singleAttrValuePojo.getAttr(), parentProductMap.get(data.getLong(ProductEnum.PARENT_ID.getAttr())));
                        productUpdateDTO.setData(updateData);
                        productUpdateList.add(productUpdateDTO);
                    }
                });
            }
            if (!productUpdateList.isEmpty()) {
                ProductUpdateBatchDTO productUpdateBatch = new ProductUpdateBatchDTO();
                BeanUtil.copyProperties(productEditAttrUpdateDTO, productUpdateBatch);
                productUpdateBatch.setProductList(productUpdateList);
                updateBatch(productUpdateBatch);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProductEntityExt item : productList) {
                dataIdList.add(item.getId());
                JSONObject data = item.getData();
                String productNo = FastJsonHelper.getStringOrDefaultFromFormData(data, ProductEnum.PRODUCT_NO.getAttr(), "");
                String opObjectName = data.getString(ProductEnum.NAME.getAttr());
                StringBuilder sb = new StringBuilder();
                opObjectName = opObjectName == null ? productNo : sb.append(opObjectName).append("（").append(productNo).append("）").toString();
                updataItemList.add(opObjectName);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = productEditAttrUpdateDTO.getUserId();
            String loginUserName = productEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = productEditAttrUpdateDTO.getFieldType();
            logHelp.analysisLabel(corpid, fieldType, productEditAttrUpdateDTO.getIsFieldDependence(), productEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(productEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.PRODUCT.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.PRODUCT.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PRODUCT, OperateTypeEnum.EDIT,
                        "", "", memo, productEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.PRODUCT.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PRODUCT, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, productEditAttrUpdateDTO.getHttpHeader());
            }
        }catch (XbbException e) {
            LOG.error("productServiceImpl.batchEditAttr 报错：", e);
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205108);
        }catch (Exception e) {
            LOG.error("productServiceImpl.batchEditAttr 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 查询数据
     * @param parentProductIdIn 父产品id
     * @param corpid 公司id
     * @param fieldList 字段
     * @return
     * @throws XbbException
     */
    private List<PaasFormDataEntityExt> findByScroll(Collection parentProductIdIn, String corpid, List<String> fieldList) throws XbbException {
        List<PaasFormDataEntityExt> productList;
        try {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termsQuery(StringConstant.JSON_DATA+StringConstant.POINT+ProductEnum.PARENT_ID.getAttr(), parentProductIdIn));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID+StringConstant.POINT+StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(productList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
        } catch (Exception e) {
            LOG.error("productServiceImpl.findByScroll 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productList;
    }

    @Override
    public JSONObject getFormatProductJsonArray(FormatRelativeProductDTO formatRelativeProductDTO) throws XbbException {
        // 获取属性
        FormatRelativeProductEntityExt formatRelativeProduct = formatRelativeProductDTO.getFormatRelativeProductEntityExt();
        Map<String, FieldAttrEntity> nowProductExplainMap = formatRelativeProductDTO.getNowProductExplainMap();
        Map<String, FieldAttrEntity> nowStockProductExplainMap = formatRelativeProductDTO.getNowStockProductExplainMap();
        JSONObject warehouseObj = formatRelativeProduct.getWarehouseObj();
        Integer businessType = formatRelativeProductDTO.getBusinessType();
        String corpid = formatRelativeProductDTO.getCorpid();

        ProductStockInfoEntity productStockInfo = formatRelativeProduct.getProductStockInfoEntity();
        if (productStockInfo == null) {
            productStockInfo = new ProductStockInfoEntity();
        }

        Long productId = formatRelativeProduct.getProductId();
        ProductEntityExt childProduct = productModel.getByKey(productId, corpid);
        boolean isCostFieldNeedHide = false;
        boolean priceHide = false;
        if (childProduct != null) {
            Long parentId = childProduct.getData().getLong(ProductEnum.PARENT_ID.getAttr());
            PaasFormDataEntityExt paasFormDataEsEntity = productModel.getByKey(parentId, corpid);
            if (paasFormDataEsEntity != null) {
                //协同团队
                Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userTeamService.getUserIdMap(Collections.singletonList(parentId), corpid, XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);
                HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                BeanUtil.copyProperties(formatRelativeProductDTO, handlerExplainDTO);
                handlerExplainDTO.setCreatorId(paasFormDataEsEntity.getCreatorId());
                handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEsEntity.getDataId(), new ArrayList<>()));
                handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEsEntity.getDataId(), new ArrayList<>()));
                handlerExplainDTO.setExplainList(new ArrayList<>(nowProductExplainMap.values()));
                isCostFieldNeedHide = ExplainUtil.isFieldNeedHide(nowProductExplainMap.getOrDefault(ProductEnum.COST.getSaasAttr(), new FieldAttrEntity()), handlerExplainDTO);
                priceHide = ExplainUtil.isFieldNeedHide(nowProductExplainMap.getOrDefault(ProductEnum.PRICE.getSaasAttr(), new FieldAttrEntity()), handlerExplainDTO);
            }
        }
        boolean priceVisible = paasFormExplainService.checkVisibleByAttr(new ArrayList<>(nowProductExplainMap.values()), ProductEnum.PRICE.getAttr());

        Long refId = formatRelativeProduct.getRefId();
        JSONArray attrArray = new JSONArray();
        JSONObject productObj = new JSONObject();
        // 获取关联产品需要展示的字段
        DetailTabBusinessProductEnum businessProductEnum = DetailTabBusinessProductEnum.getByCode(businessType, formatRelativeProductDTO.getTargetBusinessType());
        List<RelativeProductEnum> businessProductEnumList = businessProductEnum.getList();
        for (RelativeProductEnum productEnum : businessProductEnumList) {
            String saasAttr = productEnum.getSaasAttr();
            FieldAttrEntity fieldAttrEntity = null;
            if (nowProductExplainMap.containsKey(saasAttr)) {
                fieldAttrEntity = nowProductExplainMap.get(saasAttr);
            } else if (RelativeProductEnum.STATUS.getSaasAttr().equals(productEnum.getSaasAttr())) {
                fieldAttrEntity = new FieldAttrEntity();
                fieldAttrEntity.setVisible(1);
                fieldAttrEntity.setAttrName(RelativeProductEnum.STATUS.getAttrName());
                fieldAttrEntity.setVisible(RelativeProductEnum.STATUS.getVisible());
            }
            if (Objects.nonNull(fieldAttrEntity) && (Objects.equals(saasAttr, PRODUCT_PRICE.getSaasAttr()) || Objects.equals(saasAttr, COST.getSaasAttr())) && ((Objects.equals(fieldAttrEntity.getIsOpen(), 0) || (Objects.equals(fieldAttrEntity.getVisible(), 0))))) {
                continue;
            }
            switch (productEnum) {
                case NAME:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(productEnum, formatRelativeProduct.getProductName(), fieldAttrEntity));
                    break;
                case PRODUCT_NO:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCT_NO, formatRelativeProduct.getProductNo(), fieldAttrEntity));
                    break;
                case BARCODE:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BARCODE, formatRelativeProduct.getBarcode(), fieldAttrEntity));
                    break;
                case WAREHOUSE:
                    ProductWarehouseMapDTO productWarehouseMapDTO = new ProductWarehouseMapDTO();
                    BeanUtil.copyProperties(formatRelativeProductDTO, productWarehouseMapDTO);
                    productWarehouseMapDTO.setAllWarehouse(0);
                    productWarehouseMapDTO.setProductId(productId);
                    ProductWarehouseMapVO productWarehouseMapVO = warehouseService.getSelectProductWarehouses(productWarehouseMapDTO);
                    if (Objects.isNull(productWarehouseMapVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                    }
                    Map<String, JSONArray> warehouseMap = productWarehouseMapVO.getProductWarehouseMap();

                    JSONArray warehouseArray = warehouseMap.get("userWarehouseArray");
                    if (warehouseObj == null) {
                        warehouseObj = new JSONObject();
                        warehouseObj.put("id", formatRelativeProduct.getWarehouseId());
                    }
                    JSONObject warehouseResultObj = saasUpdateHelp.formatSelectProduct4Show(WAREHOUSE, warehouseObj, fieldAttrEntity);
                    if (warehouseResultObj != null) {
                        warehouseResultObj.put("attrName", I18nMessageUtil.getMessage(StringConstant.OUT_WAREHOUSE));
                        warehouseResultObj.put("warehouseArray", warehouseArray);
                        attrArray.add(warehouseResultObj);
                    }
                    break;
                case NUM:
                    if(Objects.isNull(fieldAttrEntity)) {
                        fieldAttrEntity = new FieldAttrEntity();
                    }
                    FieldAttrEntity stockAttrEntity = nowProductExplainMap.get(ProductEnum.STOCK.getSaasAttr());
                    if(Objects.nonNull(stockAttrEntity)) {
                        fieldAttrEntity.setAccuracy(stockAttrEntity.getAccuracy());
                    }
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(NUM, formatRelativeProduct.getProductNum(), fieldAttrEntity));
                    break;
                case COST:
                    // 优先获取costStr，如果没有值，则获取cost
                    String costStr = formatRelativeProduct.getCostStr();
                    JSONObject costObj;
                    if (StringUtil.isEmpty(costStr)) {
                        costObj = saasUpdateHelp.formatSelectProduct4Show(COST, formatRelativeProduct.getCost(), fieldAttrEntity);
                    } else {
                        costObj = saasUpdateHelp.formatSelectProduct4Show(COST, costStr, fieldAttrEntity);
                    }
                    if (costObj != null) {
                        costObj.put("attr", StringConstant.PRODUCT_COST);
                        if (isCostFieldNeedHide) {
                            costObj.put("hideCost", true);
                        }
                        attrArray.add(costObj);
                    }
                    break;
                case SPECIFICATION:
                    // 格式化规格
                    String specification = specificationModel.joinSpecification(formatRelativeProduct.getProductSpecification());
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(SPECIFICATION, specification, fieldAttrEntity));
                    break;
                case STOCK:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(STOCK, formatRelativeProduct.getStock(), fieldAttrEntity));
                    break;
                case UNIT:
                    // 单位回显 存的key是0,1,2 回显对应的单位
                    String productUnit = formatRelativeProduct.getProductUnit();
                    String unitStr = fieldAttrHelp.getDataDictionaryTextByValue(productUnit, fieldAttrEntity);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(UNIT, unitStr, fieldAttrEntity));
                    break;
                case PRODUCT_PRICE:
                    String productPriceStr = formatRelativeProduct.getProductPriceStr();
                    JSONObject productPriceObj;
                    if (StringUtil.isEmpty(productPriceStr)) {
                        double productPrice = formatRelativeProduct.getProductPrice() == null ? 0D : formatRelativeProduct.getProductPrice();
                        productPriceObj = saasUpdateHelp.formatSelectProduct4Show(PRODUCT_PRICE, productPrice, fieldAttrEntity);
                    } else {
                        productPriceObj = saasUpdateHelp.formatSelectProduct4Show(PRODUCT_PRICE, productPriceStr, fieldAttrEntity);
                    }
//                    if (Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode())) {
//                        // 采购合同的采购单价和小计的精度使用产品成本的精度
//                        FieldAttrEntity costFieldEntity = nowProductExplainMap.get(ProductEnum.COST.getSaasAttr());
//                        if (costFieldEntity != null && productPriceObj != null) {
//                            productPriceObj.put("accuracy", costFieldEntity.getAccuracy());
//                        }
//                    }
                    if (productPriceObj != null) {
                        // 采购合同的单价对应产品的成本，字段权限也对应产品成本的权限
//                        if(Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode())) {
//                            productPriceObj.put("hidePrice", isCostFieldNeedHide);
//                        } else {
//                            productPriceObj.put("hidePrice", priceHide);
//                            /*if (priceHide) {
//                                productPriceObj.put("attrValue", StringConstant.INVISIBLE_VALUE);
//                            }*/
//                        }
                        productPriceObj.put("hidePrice", priceHide);

                        attrArray.add(productPriceObj);
                    }
                    break;
                case SUBTOTAL:
                    Double subTotal = formatRelativeProduct.getSubTotal();
                    JSONObject subTotalObj = saasUpdateHelp.formatSelectProduct4Show(SUBTOTAL, subTotal, fieldAttrEntity);
                    /*if (Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode())) {
                        // 采购合同的采购单价和小计的精度使用产品成本的精度
                        FieldAttrEntity costFieldEntity = nowProductExplainMap.get(ProductEnum.COST.getSaasAttr());
                        if (costFieldEntity != null && subTotalObj != null) {
                            subTotalObj.put("accuracy", costFieldEntity.getAccuracy());
                        }
                    }else */if (priceHide) {
                        subTotalObj.put("attrValue" ,StringConstant.INVISIBLE_VALUE);
                    }
                    JsonHelperUtil.addToJSONArray(attrArray, subTotalObj);
                    break;
                case BATCH:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BATCH, productStockInfo.getBatch(), fieldAttrEntity));
                    break;
                case GUARANTEE_PERIOD:
                    Double period = productStockInfo.getGuaranteePeriod() == null ? 0D : productStockInfo.getGuaranteePeriod() / (double) 86400;
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(GUARANTEE_PERIOD, period, fieldAttrEntity));
                    break;
                case PRODUCE_DATE:
                    Long productDate = productStockInfo.getProduceDate();
                    String date = productDate == null ? "" : DateTimeUtil.getStringEpochSecond(productDate, DateTimeUtil.SDFDate);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCE_DATE, date, fieldAttrEntity));
                    break;
                case MEMO:
                    // 产品备注
                    String memo = formatRelativeProduct.getMemo();
                    if (memo == null) {
                        // 产品备注为空，则取库存产品的备注
                        memo = productStockInfo.getMemo();
                    }
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(MEMO, Objects.toString(memo, ""), fieldAttrEntity));
                    break;
                case SALE_PRODUCT_PRICE:
                    Double saleProductPrice = formatRelativeProduct.getSaleProductPrice();
                    // 防范科学计数法
                    BigDecimal saleProductPriceStr = new BigDecimal(saleProductPrice.toString());

                    JSONObject saleProductPriceObj = saasUpdateHelp.formatSelectProduct4Show(SALE_PRODUCT_PRICE, Objects.toString(saleProductPriceStr, ""), fieldAttrEntity);
                    if (priceHide) {
                        saleProductPriceObj.put("attrValue" ,StringConstant.INVISIBLE_VALUE);
                    }
                    JsonHelperUtil.addToJSONArray(attrArray, saleProductPriceObj);
                    break;
                case SALE_DISCOUNT:
                    Double saleDiscount = formatRelativeProduct.getSaleDiscount();
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(RelativeProductEnum.SALE_DISCOUNT, Objects.toString(saleDiscount, ""), fieldAttrEntity));
                    break;
                case SALE_SUBTOTAL:
                    Double saleSubTotal = formatRelativeProduct.getSaleSubtotal();
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(RelativeProductEnum.SALE_SUBTOTAL, saleSubTotal, fieldAttrEntity));
                    break;
                case LACK_NUM:
                    Double lackNum = formatRelativeProduct.getLackNum();
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(RelativeProductEnum.LACK_NUM, lackNum, fieldAttrEntity));
                    break;
                case STATUS:
                    String status = formatRelativeProduct.getStatus();
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(RelativeProductEnum.STATUS, status, fieldAttrEntity));
                    break;
                case THUMBNAIL:
                    String imageUrl = StringUtil.isEmpty(formatRelativeProduct.getImageUrl()) ? StringConstant.DEFAULT_IMAGES : formatRelativeProduct.getImageUrl();
                    List<String> imageUrlList = new ArrayList<>();
                    imageUrlList.add(imageUrl);
                    productObj.put(ProductEnum.THUMBNAIL.getSaasAttr(), imageUrlList);
                    break;
                default:
                    break;
            }

        }
        productObj.put(StringConstant.RESULT, attrArray);
        productObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, productId);
        productObj.put(StringConstant.BUSINESS_PRODUCT_ID, refId);
        if (Objects.equals(formatRelativeProductDTO.getFromDefault(), BasicConstant.ONE)) {
            productObj.put(StringConstant.ESTIMATE_COST, formatRelativeProduct.getCost());
        }
        productObj.put("parentId", formatRelativeProduct.getParentId());
        // TODO 库存产品自定义字段的回显
        return productObj;
    }

    /**
     * 产品名称或编号模糊查询（得到产品名（编号）的结果）
     *
     * @param productSearchDTO corpid, nameOrNoLike
     * @return java.util.List<com.xbongbong.pro.product.pojo.vo.ProductSearchDetailVO>
     * @throws XbbException getParentIdNoMap抛出异常
     * @author 徐俊杰
     * @date 2019/4/11 9:23
     * @since v1.0
     */
    @Override
    public ProductSearchVO productSearch(ProductSearchDTO productSearchDTO) throws XbbException {
        ProductSearchVO productSearchVO = new ProductSearchVO();
        try {
            //产品名称或编号模糊查询
            XbbAggregatedPage<PaasFormDataEntity> esEntities = listOfSelectProduct(productSearchDTO);
            //分页信息
            Integer page = productSearchDTO.getPage();
            Integer pageSize = productSearchDTO.getPageSize();
            List<PaasFormDataEntity> productList = new ArrayList<>();
            int rowCounts = 0;
            if (esEntities != null) {
                productList = esEntities.getContent();
                rowCounts = (int) esEntities.getTotalElements();
            }
            //设置分页相关信息
            PageHelper pageHelper = PageHelperUtil.initPageHelper(rowCounts, page, pageSize, pageSize);
            productSearchVO.setPageHelper(pageHelper);
            //封装回参
            List<ProductSearchDetailVO> productSearchDetailVOS = productSearchFormat(productList);
            productSearchVO.setProductSearchDetailVOS(productSearchDetailVOS);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("productServiceImpl.productSearch 产品查询报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productSearchVO;
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        // 初始化数据
        JSONObject dataJson = SaasDataInitHelp.initProduct();
        dataJson.put(ProductEnum.COST.getAttr(), 0.0);
        dataJson.put(ProductEnum.PRICE.getAttr(), 0.0);
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        //遍历excel中数据 拿到单位栏的索引 text 和 value 便于下面单价的处理
        Integer unitIndex = null;
        String unitText = null;
        Long unitGroupId = null;
        Map<Long, List<UnitItemPoJo>> groupItemsMap = relativeProductHelp.getGroupItemsMap(importFormDataDTO.getCorpid());
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if(Objects.equals(attr, ProductEnum.UNIT.getAttr())){
                unitIndex = columnIndex;
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                }
                unitText = cellValue.toString();
                if(!dataJson.containsKey(fieldAttrEntityForImport.getAttr()) || StringUtils.isEmpty(unitText)){
                    break;
                }else if (StringUtil.isDigital(dataJson.get(fieldAttrEntityForImport.getAttr()).toString())){
                    unitGroupId = Long.valueOf(dataJson.get(fieldAttrEntityForImport.getAttr()).toString());
                    break;
                }
            }

        }
        //根据单位value 拼是否开始多单位标示
        dataJson.put(ProductEnum.ENABLE_MULTI_UNIT.getAttr(), BasicConstant.ZERO);
        if(Objects.nonNull(unitGroupId) && StringUtil.isDigital(unitGroupId.toString()) && Long.parseLong(unitGroupId.toString()) > ProductConstant.MAX_SINGLE_UNIT_VALUE){
            dataJson.put(ProductEnum.ENABLE_MULTI_UNIT.getAttr(), BasicConstant.ONE);
        }

        // 遍历解释
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if(Objects.equals(attr, ProductEnum.SHELF_LIFE_DAYS.getAttr()) && !StringUtil.isEmpty(cellValue.toString())){
                if (Long.parseLong(String.valueOf(cellValue)) > 36500){
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205077);
                }
            }

            //多单位价格格式转换
            if (Objects.equals(attr, ProductEnum.PRICE.getAttr()) && Objects.nonNull(unitIndex) && Objects.nonNull(unitGroupId) && unitGroupId > 1000){
                //根据用户输入的单价字符串 转换为数组
                List<Double> priceList = importHelper.checkImportDataForPirce(cellValue.toString());
                //根据单位组的text分割出单位组的比例
                String[] split = unitText.split("=");
                //防止单位名称有输入= 时分割出现错误
                if (!Objects.equals(BasicConstant.TWO, split.length)){
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205099);
                }
                String[] unitRate = split[1].split(":");
                // 单位组比例list
                List<Double> unitRateList = new ArrayList<>();
                for (int i = 0; i < unitRate.length; i++) {
                    unitRateList.add(Double.valueOf(unitRate[i]));
                }
                //单价的自动填充
                List<Double> priceRateList = importHelper.unitConversion(priceList, unitRateList);
                //单价格式转换
                List<MultiUnitPricePoJo> multiUnitPricePoJos = importHelper.priceRate(priceRateList, unitGroupId, groupItemsMap);
                dataJson.put(ProductEnum.PRICE.getAttr(), JSONArray.parseArray(JSON.toJSONString(multiUnitPricePoJos)));
            }else if (Objects.equals(attr, ProductEnum.PRICE.getAttr()) ){
                if(Objects.nonNull(cellValue) && StringUtil.isNotEmpty(cellValue.toString()) && !StringUtil.isDigital(cellValue.toString())){
                    throw new XbbException(ProductErrorCodeEnum.API_ERROR_205110);
                }
                if (StringUtil.isDigital(cellValue.toString())){
                    dataJson.put(ProductEnum.PRICE.getAttr(), cellValue);
                }
            }
            if (Objects.equals(attr, ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr())){
                if (StringUtil.isEmpty(cellValue.toString())){
                    dataJson.put(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr(),BasicConstant.ZERO);
                }
            }
            if (Objects.equals(attr, ProductEnum.ENABLE_SERIAL_NUMBER.getAttr())){
                if (StringUtil.isEmpty(cellValue.toString())){
                    dataJson.put(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr(),BasicConstant.ZERO);
                }
            }
            if (Objects.equals(attr, ProductEnum.SPECIFICATION.getAttr())) {
                if (rowValueList.size() == 1 && !JsonHelperUtil.isJSONValid(Objects.toString(cellValue, ""))) {
                    JSONObject specObject = new JSONObject();
                    specObject.put(ProductConstant.ADVANCED_MODE, 0);
                    specObject.put(ProductConstant.SINGLE_SPEC, cellValue.toString());
                    specObject.put(ProductConstant.MUTIL_SPEC_DETAILS, new JSONArray());
                    specObject.put(ProductConstant.SPEC_VALUE, new JSONArray());
                    dataJson.put(attr, specObject);
                } else {
                    JSONObject specObject = new JSONObject();
                    specObject.put(ProductConstant.ADVANCED_MODE, 1);
                    JSONArray childProduct = new JSONArray();
                    List<String> specList = new ArrayList<>();
                    Set<String> specSet = new HashSet<>(rowValueList.size());
                    for (int i = 0; i < rowValueList.size(); i++) {
                        List<CellValuePojo> cellValuePoos = rowValueList.get(i);
                        JSONObject childProductObject = new JSONObject();
                        childProductObject.put(ProductConstant.ENABLE, 1);
                        for (FieldAttrEntityForImport forImport : fieldAttrList) {
                            if (Objects.equals(forImport.getAttr(), ProductEnum.COST.getAttr())) {
                                String subAttrName = forImport.getAttrName();
                                Integer subColumnIndex = importHelper.getColumnIndexByTitle(titlePojoList, subAttrName, null);
                                Object subFormCellValue = importHelper.getValueByColumnIndex(cellValuePoos, subColumnIndex);
                                childProductObject.put(ProductEnum.COST.getAttr(), subFormCellValue);
                            } else if (Objects.equals(forImport.getAttr(), ProductEnum.PRICE.getAttr())) {
                                String subAttrName = forImport.getAttrName();
                                Integer subColumnIndex = importHelper.getColumnIndexByTitle(titlePojoList, subAttrName, null);
                                Object subFormCellValue = importHelper.getValueByColumnIndex(cellValuePoos, subColumnIndex);
                                //多规格 多单位 单价处理
                                if (Objects.nonNull(unitIndex) && Objects.nonNull(unitGroupId) && unitGroupId > 1000){
                                    //根据用户输入的单价字符串 转换为数组
                                    List<Double> priceList = importHelper.checkImportDataForPirce(subFormCellValue.toString());
                                    //根据单位组的text分割出单位组的比例
                                    String[] split = unitText.split("=");
                                    //防止单位名称有输入= 时分割出现错误
                                    if (!Objects.equals(BasicConstant.TWO, split.length)){
                                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205099);
                                    }
                                    String[] unitRate = split[1].split(":");
                                    // 单位组比例list
                                    List<Double> unitRateList = new ArrayList<>();
                                    for (int j = 0; j < unitRate.length; j++) {
                                        unitRateList.add(Double.valueOf(unitRate[j]));
                                    }
                                    //单价的自动填充
                                    List<Double> priceRateList = importHelper.unitConversion(priceList, unitRateList);
                                    //单价格式转换
                                    List<MultiUnitPricePoJo> multiUnitPricePoJos = importHelper.priceRate(priceRateList, unitGroupId, groupItemsMap);
                                    childProductObject.put(ProductEnum.PRICE.getAttr(), multiUnitPricePoJos);
                                }else {
                                    childProductObject.put(ProductEnum.PRICE.getAttr(), subFormCellValue);
                                }

                            } else if (Objects.equals(forImport.getAttr(), ProductEnum.SERIALNO.getAttr())) {
                                String subAttrName = forImport.getAttrName();
                                Integer subColumnIndex = importHelper.getColumnIndexByTitle(titlePojoList, subAttrName, null);
                                Object subFormCellValue = importHelper.getValueByColumnIndex(cellValuePoos, subColumnIndex);
                                subFormCellValue = null == subFormCellValue ? "" : subFormCellValue;
                                childProductObject.put(ProductConstant.SPEC_CODE, subFormCellValue.toString() + "." +i);
                            } else if (Objects.equals(forImport.getAttr(), ProductEnum.SPECIFICATION.getAttr())) {
                                String subAttrName = forImport.getAttrName();
                                Integer subColumnIndex = importHelper.getColumnIndexByTitle(titlePojoList, subAttrName, null);
                                Object subFormCellValue = importHelper.getValueByColumnIndex(cellValuePoos, subColumnIndex);
                                childProductObject.put(ProductConstant.SPEC_TYPE, subFormCellValue.toString());
                                specList.add(subFormCellValue.toString());
                                specSet.add(subFormCellValue.toString());
                            } else if (Objects.equals(forImport.getAttr(), ProductEnum.BARCODE.getAttr())) {
                                String subAttrName = forImport.getAttrName();
                                Integer subColumnIndex = importHelper.getColumnIndexByTitle(titlePojoList, subAttrName, null);
                                Object subFormCellValue = importHelper.getValueByColumnIndex(cellValuePoos, subColumnIndex);
                                childProductObject.put(ProductConstant.PRODUCT_CODE, subFormCellValue);
                            }
                        }
                        childProduct.add(childProductObject);
                    }
                    if (specSet.size() < specList.size()) {
                        throw new XbbException(ImportErrorCodeEnum.API_ERROR_235045);
                    }
                    specObject.put(ProductConstant.MUTIL_SPEC_DETAILS, childProduct);
                    // todo 规格值的顺序用json接收会变得无序
                    JSONArray specArray = new JSONArray();
                    Set<String> allKey = new LinkedHashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    try {
                        for (String item : specList) {
                            item = item.replaceAll("“","\"");
                            JSONObject itemObj = JSON.parseObject(item, JSONObject.class, Feature.OrderedField);
                            allKey.addAll(itemObj.keySet());
                        }
                    } catch (Exception e) {
                        LOG.error("多规格产品规格字段格式错误", e);
                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205055);
                    }
                    for (String item : specList) {
                        JSONObject itemObj = JSON.parseObject(item, JSONObject.class, Feature.OrderedField);
                        for (String key : allKey) {
                            String value = itemObj.getString(key);
                            JSONObject jsonObject = getByKey(specArray, key);
                            JSONArray valueArray = jsonObject.getJSONArray("value");
                            if (StringUtil.isEmpty(value.toString()) || Objects.isNull(value)){
                                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205113);
                            }
                            if (value != null && !valueArray.contains(value)) {
                                valueArray.add(value);
                            }
                        }
                    }
                    specObject.put(ProductConstant.SPEC_VALUE, specArray);
                    dataJson.put(attr, specObject);
                }
            }  else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else if (Objects.equals(attr, ProductEnum.SUPPLIER.getAttr()) || Objects.equals(attr, ProductEnum.WAREHOUSE.getAttr())) {
                    importHelper.formatLinkBusinessValue4Import(dataJson, fieldAttrEntityForImport, cellValue);
                } else {
                    if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                        formDataAddDTO.setSerialNo(cellValue.toString());
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                        importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                    } else {
                        //单价在上面处理
                        if (!Objects.equals(ProductEnum.PRICE.getAttr(), attr)){
                            dataJson.put(attr, cellValue);
                        }

                    }
                }
            }
        }
        if (formDataAddDTO.getOwnerId() == null) {
            ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = new ReturnUserAndDepartmentPojo();
            returnUserAndDepartmentPojo.setId(importFormDataDTO.getUserId());
            formDataAddDTO.setOwnerId(Collections.singletonList(returnUserAndDepartmentPojo));
        }
        if (formDataAddDTO.getDepartmentId() == null) {
            formDataAddDTO.setDepartmentId(0L);
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }



    @Override
    public List<PaasFormDataEntityExt> getProductListById(Set<Long> productIds, String corpid, DelEnum delEnum) throws XbbException {
        return productModel.getProductListById(productIds, corpid, delEnum);
    }

    @Override
    public Map<Long,PaasFormDataEntityExt> getProductMapByIdIn(Set<Long> productIds, String corpid,DelEnum delEnum) throws XbbException {
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = getProductListById(productIds,corpid,delEnum);
        Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList){
            productMap.put(entityExt.getDataId(),entityExt);
        }
        return productMap;
    }

    @Override
    public void formatStockSearchExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) {

        List<PaasFormDataEntityExt> allChildList = new ArrayList<>();
        Map<Long, JSONArray> warehouseMap = formDataListDTO.getChildProductMap();
        for (PaasFormDataEntityExt formDataEntityExt : paasFormDataESList) {

            String spec = formDataEntityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
            if (Objects.equals(spec, "{}")) {
                formDataEntityExt.getData().put(ProductEnum.SPECIFICATION.getAttr(), "");
            } else {
                formDataEntityExt.getData().put(ProductEnum.SPECIFICATION.getAttr(), spec);
            }

            JSONArray warehouseArray = warehouseMap.get(formDataEntityExt.getDataId());
            if (Objects.nonNull(warehouseArray) && !warehouseArray.isEmpty()) {
                for (int i = 0; i < warehouseArray.size(); i++) {
                    JSONObject childObject = warehouseArray.getJSONObject(i);
                    // 遇到fastJson：default constructor not found问题用fastJson方法替代CloneUtil.deepClone实现深克隆 edit by kaka
                    PaasFormDataEntityExt childEntity = JSON.parseObject(JSON.toJSONString(formDataEntityExt), PaasFormDataEntityExt.class);
                    JSONObject childData = childEntity.getData();
                    childData.put(ProductEnum.WAREHOUSE.getAttr(),childObject.getString(ProductEnum.WAREHOUSE.getSaasAttr()));
                    childData.put(ProductEnum.COST.getAttr(),childObject.getString(ProductEnum.COST.getSaasAttr()));
                    if (Objects.equals(childObject.getString(ProductEnum.COST.getSaasAttr()), BasicConstant.NULL_SHOW_STR)) {
                        childData.put(ProductEnum.COST.getAttr(), null);
                    }
                    /*if (isCostFieldNeedHide) {
                        childData.put(ProductEnum.COST.getAttr(), null);
                    }*/
                    if (Objects.equals(childObject.getString(ProductEnum.STOCK.getSaasAttr()), BasicConstant.NULL_SHOW_STR)) {
                        childData.put(ProductEnum.STOCK.getAttr(), null);
                    } else {
                        childData.put(ProductEnum.STOCK.getAttr(),childObject.getDouble(ProductEnum.STOCK.getSaasAttr()));
                    }
                    String unitText = childData.getString(ProductEnum.UNIT.getAttr());
                    if (Objects.nonNull(unitText) && StringUtil.isNotEmpty(unitText)){
                        if (unitText.contains("=") && unitText.contains(":")){
                            childData.put(ProductEnum.UNIT.getAttr(), unitText.split(":")[0]);
                        }
                    }
                    allChildList.add(childEntity);
                }
            }
        }
        paasFormDataESList.clear();
        paasFormDataESList.addAll(allChildList);
    }

    @Override
    public void formatWarningSearchExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) {
        List<Long> dataIdList = new ArrayList<>();
        for (PaasFormDataEntityExt paasFormDataEsEntity : paasFormDataESList) {
            dataIdList.add(paasFormDataEsEntity.getId());
        }
        // 协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userTeamService.getUserIdMap(dataIdList, formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);
        // 成本字段解释
        FieldAttrEntity costField = new FieldAttrEntity();
        FieldAttrEntity stockField = new FieldAttrEntity();
        List<FieldAttrEntity> fieldAttrEntityList = new ArrayList<>();
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            BeanUtil.copyProperties(fieldAttrEntityForImport, fieldAttrEntity);
            fieldAttrEntityList.add(fieldAttrEntity);
            if (Objects.equals(fieldAttrEntity.getAttr(), ProductEnum.COST.getAttr())) {
                costField = fieldAttrEntity;
            }else if (Objects.equals(fieldAttrEntity.getAttr(), "currentStock")) {
                stockField = fieldAttrEntity;
            }
        }
        for (PaasFormDataEntityExt formDataEntityExt : paasFormDataESList) {
            ProductWarehouseEntity productWarehouseEntity = formDataEntityExt.getProductWarehouseEntity();
            Long parentId = formDataEntityExt.getDataId();
            JSONObject data = formDataEntityExt.getData();
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);
            handlerExplainDTO.setCreatorId(formDataEntityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setExplainList(fieldAttrEntityList);
            boolean isCostFieldNeedHide = false;
            boolean isStockFieldNeedHide = false;
            try {
                isCostFieldNeedHide = ExplainUtil.isFieldNeedHide(costField, handlerExplainDTO);
                isStockFieldNeedHide = ExplainUtil.isFieldNeedHide(stockField, handlerExplainDTO);
                String spec = data.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                if (Objects.equals(spec, "{}")) {
                    data.put(ProductEnum.SPECIFICATION.getAttr(), "");
                } else {
                    data.put(ProductEnum.SPECIFICATION.getAttr(), spec);
                }
                String unitText = data.getString(ProductEnum.UNIT.getAttr());
                if (Objects.nonNull(unitText) && StringUtil.isNotEmpty(unitText)){
                    if (unitText.contains("=") && unitText.contains(":")){
                        data.put(ProductEnum.UNIT.getAttr(), unitText.split(":")[0]);
                    }
                }
            } catch (Exception e) {
                LOG.error("formatStockSearchExportValue", e);
            }
            if (Objects.nonNull(productWarehouseEntity)) {
                if (isStockFieldNeedHide){
                    data.put("currentStock",null);
                    data.put("lowerLimit", null);
                    data.put("upperLimit", null);
                }else {
                    data.put("currentStock",productWarehouseEntity.getNum());
                    data.put("lowerLimit", productWarehouseEntity.getStockLowerLimit());
                    data.put("upperLimit", productWarehouseEntity.getStockUpperLimit());
                }
                data.put(ProductEnum.WAREHOUSE.getAttr(), productWarehouseEntity.getWarehouseName());
                if (productWarehouseEntity.getNum() > productWarehouseEntity.getStockUpperLimit()) {
                    // 超上限
                    data.put("warningType", I18nMessageUtil.getMessage(BusinessConstant.WARNING_UPPER));
                    data.put("overLimit", productWarehouseEntity.getNum() - productWarehouseEntity.getStockUpperLimit());
                } else {
                    // 超下限
                    data.put("warningType", I18nMessageUtil.getMessage(BusinessConstant.WARNING_LOWER));
                    data.put("overLimit", productWarehouseEntity.getStockLowerLimit() - productWarehouseEntity.getNum());
                }
            }
            if (isCostFieldNeedHide) {
                data.put(ProductEnum.COST.getAttr(), null);
            }
        }
    }

    @Override
    public void formatGuaranteeSearchExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        List<Long> dataIdList = new ArrayList<>();
        for (PaasFormDataEntityExt paasFormDataEsEntity : paasFormDataESList) {
            dataIdList.add(paasFormDataEsEntity.getId());
        }
        // 协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userTeamService.getUserIdMap(dataIdList, formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);
        // 成本字段解释
        FieldAttrEntity costField = new FieldAttrEntity();
        FieldAttrEntity stockField = new FieldAttrEntity();
        List<FieldAttrEntity> fieldAttrEntityList = new ArrayList<>();
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            BeanUtil.copyProperties(fieldAttrEntityForImport, fieldAttrEntity);
            fieldAttrEntityList.add(fieldAttrEntity);
            if (Objects.equals(fieldAttrEntity.getAttr(), SelectProductEnum.COST.getSaasAttr())) {
                costField = fieldAttrEntity;
            }else if (Objects.equals(fieldAttrEntity.getAttr(), SelectProductEnum.STOCK.getSaasAttr())) {
                stockField = fieldAttrEntity;
            }
        }
        for (PaasFormDataEntityExt formDataEntityExt : paasFormDataESList) {
            Long parentId = formDataEntityExt.getDataId();
            JSONObject data = formDataEntityExt.getData();
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);
            handlerExplainDTO.setCreatorId(formDataEntityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(parentId, new ArrayList<>()));
            handlerExplainDTO.setExplainList(fieldAttrEntityList);
            String spec = data.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
            if (Objects.equals(spec, "{}")) {
                data.put(ProductEnum.SPECIFICATION.getAttr(), "");
            } else {
                data.put(ProductEnum.SPECIFICATION.getAttr(), spec);
            }
            if (Objects.nonNull(data.get(SelectProductEnum.PRODUCE_DATE.getSaasAttr()))) {
                data.put(SelectProductEnum.PRODUCE_DATE.getSaasAttr(), DateTimeUtil.getStringEpochSecond(data.getLong(SelectProductEnum.PRODUCE_DATE.getSaasAttr()), DateTimeUtil.SDFDate));
            }
            if (Objects.isNull(data.get(SelectProductEnum.PRODUCE_DATE.getSaasAttr()))) {
                data.remove(SelectProductEnum.GUARANTEE_PERIOD.getSaasAttr());
            }
            if (Objects.nonNull(data.get(SelectProductEnum.EXPIRE_DATE.getSaasAttr()))) {
                try {
                    data.put(SelectProductEnum.EXPIRE_DATE.getSaasAttr(), DateTimeUtil.getStringEpochSecond(data.getLong(SelectProductEnum.EXPIRE_DATE.getSaasAttr()), DateTimeUtil.SDFDate));
                } catch (Exception e) {

                }
            }
            boolean isCostFieldNeedHide = false;
            boolean isStockFieldNeedHide = false;
            try {
                isCostFieldNeedHide = ExplainUtil.isFieldNeedHide(costField, handlerExplainDTO);
                isStockFieldNeedHide = ExplainUtil.isFieldNeedHide(stockField, handlerExplainDTO);
            } catch (Exception e) {
                LOG.error("formatStockSearchExportValue", e);
            }
            if (isCostFieldNeedHide) {
                data.put(SelectProductEnum.COST.getSaasAttr(), null);
                data.put(SelectProductEnum.TOTAL_COST.getSaasAttr(), null);
            }
            if (isStockFieldNeedHide) {
                data.put(SelectProductEnum.STOCK.getSaasAttr(), null);
            }
            String unitText = data.getString(ProductEnum.UNIT.getAttr());
            if (Objects.nonNull(unitText) && StringUtil.isNotEmpty(unitText)){
                if (unitText.contains("=") && unitText.contains(":")){
                    data.put(ProductEnum.UNIT.getAttr(), unitText.split(":")[0]);
                }
            }
        }
    }

    @Override
    public Object getCostBySummary(List<PaasFormDataEntityExt> childProductESList, String corpid, Long formDataId) throws XbbException {
        if (childProductESList.isEmpty()) {
            childProductESList = getDataByParentId(corpid, formDataId);
        }
        if (childProductESList.isEmpty()) {
            return "";
        }
        PaasFormDataEntityExt paasFormDataEsEntity = childProductESList.get(0);
        Integer advancedMode = getIntegerOrDefaultFromFormData(paasFormDataEsEntity.getData(), ProductEnum.SPECIFICATION.getAttr(), 0);
        boolean multiSpec = Objects.equals(advancedMode, 1);
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());
        FieldAttrEntity priceAttrEntity = explainMap.get(ProductEnum.COST.getAttr());
        if (multiSpec) {
            String priceStr = getPriceOrCostRegion(childProductESList, ProductEnum.COST.getAttr(), priceAttrEntity.getAccuracy());
            return priceStr;
        } else if (Objects.nonNull(paasFormDataEsEntity)){
            JSONObject data = paasFormDataEsEntity.getData();
            return AttrDecimalPrecisionHelper.parseThousandth(data.getDouble(ProductEnum.COST.getAttr()), priceAttrEntity.getAccuracy());
        }
        return "";
    }

    @Override
    public void formatWaitInstockProductExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO) throws XbbException {
        for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList){
            JSONObject data = paasFormDataEntityExt.getData();
            //处理产品名称
            String productName = data.getJSONArray(WaitInstockEnum.PRODUCT_NAME.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.PRODUCT_NAME.getAttr(),productName);
            //处理产品编号
            String productNo = data.getJSONArray(WaitInstockEnum.PRODUCT_NO.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.PRODUCT_NO.getAttr(),productNo);
            //处理采购合同名称
            String purchaseName = data.getJSONArray(WaitInstockEnum.PURCHASE_NAME.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.PURCHASE_NAME.getAttr(),purchaseName);
            //处理采购合同编号
            String purchaseNo = data.getJSONArray(WaitInstockEnum.SHEET_NO.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.SHEET_NO.getAttr(),purchaseNo);
            //处理供应商
            String supplier = data.getJSONArray(WaitInstockEnum.SUPPLIER_ID.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.SUPPLIER_ID.getAttr(),supplier);
            //处理时间格式
            String addTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.ADD_TIME.getAttr()), DateTimeUtil.SDF);
            String updateTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.UPDATE_TIME.getAttr()), DateTimeUtil.SDF);
            String signTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitInstockEnum.SIGN_TIME.getAttr()), DateTimeUtil.SDFDate);
            String arriveTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitInstockEnum.ESTIMATE_ARRIVE_TIME.getAttr()), DateTimeUtil.SDFDate);
            data.put(PurchaseEnum.ADD_TIME.getAttr(),addTime);
            data.put(PurchaseEnum.UPDATE_TIME.getAttr(),updateTime);
            data.put(PurchaseEnum.SIGN_TIME.getAttr(),signTime);
            data.put(PurchaseEnum.ESTIMATE_ARRIVE_TIME.getAttr(),arriveTime);

        }
    }

    @Override
    public void formatWaitPurchaseProductExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO) throws XbbException {
        for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList){
            JSONObject data = paasFormDataEntityExt.getData();
            //处理产品名称
            String productName ="";
            if (CollectionUtils.isNotEmpty(data.getJSONArray(WaitPurchaseProductEnum.PRODUCT_NAME.getAttr()))){
                productName = data.getJSONArray(WaitPurchaseProductEnum.PRODUCT_NAME.getAttr()).getJSONObject(0).getString("name");
            }
            data.put(WaitPurchaseProductEnum.PRODUCT_NAME.getAttr(),productName);
            //处理产品编号
            String productNo = "";
            if(CollectionUtils.isNotEmpty(data.getJSONArray("productSerialNo"))){
                productNo = data.getJSONArray("productSerialNo").getJSONObject(0).getString("name");
            }
            data.put("productSerialNo",productNo);
            //处理合同名称
            String purchaseName = "";
            if (CollectionUtils.isNotEmpty(data.getJSONArray(WaitPurchaseContractEnum.NAME.getAttr())))   {
                purchaseName= data.getJSONArray(WaitPurchaseContractEnum.NAME.getAttr()).getJSONObject(0).getString("name");
            }
            data.put(WaitPurchaseContractEnum.NAME.getAttr(),purchaseName);
            //处理客户名称
            String customerName = "";
            if(CollectionUtils.isNotEmpty(data.getJSONArray(WaitPurchaseContractEnum.LINK_CUSTOMER.getAttr()))){
                customerName = data.getJSONArray(WaitPurchaseContractEnum.LINK_CUSTOMER.getAttr()).getJSONObject(0).getString("name");
            }
            data.put(WaitPurchaseContractEnum.LINK_CUSTOMER.getAttr(),customerName);
            //处理合同编号
            String purchaseNo = "";
            if (CollectionUtils.isNotEmpty(data.getJSONArray(WaitPurchaseContractEnum.CONTRACT_NO.getAttr()))){
                purchaseNo = data.getJSONArray(WaitPurchaseContractEnum.CONTRACT_NO.getAttr()).getJSONObject(0).getString("name");
            }
            data.put(WaitPurchaseContractEnum.CONTRACT_NO.getAttr(),purchaseNo);
            //处理供应商
            String supplier = "";
            if (CollectionUtils.isNotEmpty(data.getJSONArray(WaitPurchaseProductEnum.SUPPLIER.getAttr()))){
                supplier = data.getJSONArray(WaitPurchaseProductEnum.SUPPLIER.getAttr()).getJSONObject(0).getString("name");
            }
            data.put(WaitPurchaseProductEnum.SUPPLIER.getAttr(),supplier);
            //处理时间格式
            String addTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.ADD_TIME.getAttr()), DateTimeUtil.SDF);
            String updateTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.UPDATE_TIME.getAttr()), DateTimeUtil.SDF);
            data.put(PurchaseEnum.ADD_TIME.getAttr(),addTime);
            data.put(PurchaseEnum.UPDATE_TIME.getAttr(),updateTime);
        }
    }

    @Override
    public void formatSmartReplenishmentExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO) throws XbbException {
        for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList){
            JSONObject data = paasFormDataEntityExt.getData();
            //处理产品名称
            String productName = data.getString(SmartReplenishmentEnum.PRODUCT_NAME.getAttr());
            data.put(SmartReplenishmentEnum.PRODUCT_NAME.getAttr(),productName);
            //处理供应商
            JSONArray jsonArray = data.getJSONArray(SmartReplenishmentEnum.SUPPLIER.getAttr());
            if (CollectionsUtil.isNotEmpty(jsonArray)){
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    sb.append(jsonObject.get("name")).append(StringConstant.COMMA);
                    data.put(SmartReplenishmentEnum.SUPPLIER.getAttr(),sb);
                }
            }else {
                data.put(SmartReplenishmentEnum.SUPPLIER.getAttr(),"");
            }
        }
    }

    @Override
    public Set<Long> associateWithWarehouse(ProductWithWarehousePojo productWithWarehousePojo) throws XbbException {
        String corpid = productWithWarehousePojo.getCorpid();
        Long productId = productWithWarehousePojo.getProductId();
        Map<Long, String> warehouseNameMap = productWithWarehousePojo.getWarehouseNameMap();
        ChildProductVO childProductVO = productWithWarehousePojo.getChildProductVO();
        List<Long> addIdList = childProductVO.getAddIdList() == null ? new ArrayList<>() : childProductVO.getAddIdList();
        List<Long> editIdList = childProductVO.getEditIdList() == null ? new ArrayList<>() : childProductVO.getEditIdList();
        List<Long> delIdList = childProductVO.getDelIdList() == null ? new ArrayList<>() : childProductVO.getDelIdList();;
        List<ProductEntityExt> existProductList = childProductVO.getExistProductList();
        Map<Long, ProductEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        existProductList.forEach(product -> productMap.put(product.getId(), product));
        Map<Long, Map<String, String>> specMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 将规格值与子产品id对应起来
        for (ProductEntityExt productEntityExt : existProductList) {
            Integer singleOrMutilSpec = getIntegerFromFormData(productEntityExt.getData(), ProductEnum.SPECIFICATION.getAttr());
            if (Objects.equals(singleOrMutilSpec, 0)) {
                String spec = FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "");
                Map<String, String> singleSpecMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                singleSpecMap.put(spec, spec);
                specMap.put(productEntityExt.getId(), singleSpecMap);
            } else if (Objects.equals(singleOrMutilSpec, 1)) {
                JSONObject specObj = FastJsonHelper.getJsonObjectOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), new JSONObject());
                Map<String, String> mutuiSpecMap = JSONObject.parseObject(specObj.toJSONString(), new TypeReference<Map<String, String>>(){});
                specMap.put(productEntityExt.getId(), mutuiSpecMap);
            }
        }
        Map<String, StockNotifyPojo> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<StockNotifyPojo>> warehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<StockNotifyPojo> stockNotifyPojoList = productWithWarehousePojo.getStockNotifyPojoList();
        // 预警匹配封装
        if (CollectionsUtil.isNotEmpty(stockNotifyPojoList)) {
            for (StockNotifyPojo stockNotifyPojo : stockNotifyPojoList) {
                JSONArray specArr = stockNotifyPojo.getArray_1();
                Map<String, String> notifySpecMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (int i = 0; i < specArr.size(); i++) {
                    notifySpecMap.putAll(JSONObject.parseObject(specArr.getJSONObject(i).toJSONString(), new TypeReference<Map<String, String>>() {
                    }));
                }
                for (Map.Entry<Long, Map<String, String>> entry : specMap.entrySet()) {
                    Map<String, String> value = entry.getValue();
                    if (Objects.equals(value, notifySpecMap)) {
                        stockNotifyPojo.setProductId(entry.getKey());
                        stockNotifyPojo.setProductName(value.values().toString());
                    }
                }
                stockNotifyPojo.setWarehouseId(stockNotifyPojo.getText_1().getJSONObject(0).getLong(StringConstant.SAAS_LINK_BUSINESS_ID));
                stockNotifyPojo.setWarehouseName(stockNotifyPojo.getText_1().getJSONObject(0).getString(StringConstant.SAAS_LINK_BUSINESS_NAME));
            }
            for (StockNotifyPojo stock : stockNotifyPojoList) {
                stockMap.put(stock.getProductId() +StringConstant.CROSS + stock.getWarehouseId(), stock);
                List<StockNotifyPojo> stockNotifyPojos = new ArrayList<>();
                if (warehouseStockMap.containsKey(stock.getWarehouseId())) {
                    stockNotifyPojos = warehouseStockMap.get(stock.getWarehouseId());
                }
                stockNotifyPojos.add(stock);
                warehouseStockMap.put(stock.getWarehouseId(), stockNotifyPojos);
            }
        }
//        Double parentCost = productWithWarehousePojo.getParentCost();
//        Boolean updateCost = productWithWarehousePojo.getUpdateCost();
        ProductWarehouseSavePojo productWarehouseSavePojo = productWithWarehousePojo.getProductWarehouseSavePojo();
        if (Objects.isNull(productWarehouseSavePojo)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        Set<Long> newWarehouseIds = productWarehouseSavePojo.getNewWarehouseIds();
        Set<Long> copyWarehouseIds = productWarehouseSavePojo.getCopyWarehouseIds();
        List<Long> noPermissionWarehouseList = productWarehouseSavePojo.getNoPermissionWarehouseList();
        Set<Long> oldWarehouseIds = productWarehouseSavePojo.getOldWarehouseIds();
        List<ProductWarehouseEntity> productWarehouseList = productWarehouseSavePojo.getProductWarehouseEntityList();
        // 删除的仓库
        List<ProductWarehouseEntity> wantDelWarehouseList = new ArrayList<>();
        //被解绑仓库列表
        Map<String,ProductWarehouseEntity> unbundleMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        if (CollectionsUtil.isNotEmpty(oldWarehouseIds)) {
        for (ProductWarehouseEntity productWarehouseEntity : productWarehouseList) {
            //如果需要删除，肯定不需要恢复绑定了
            if (oldWarehouseIds.contains(productWarehouseEntity.getWarehouseId())) {
                wantDelWarehouseList.add(productWarehouseEntity);
            } else if (Objects.equals(productWarehouseEntity.getWarehouseChecked(),0)) {
                unbundleMap.put(productWarehouseEntity.getWarehouseKey(),productWarehouseEntity);
            }
        }
//        }
        List<ProductWarehouseEntity> batchAddList = new ArrayList<>();
        //恢复绑定的仓库
        List<ProductWarehouseEntity> rebundleList = new ArrayList<>();
        // 新增的仓库，需要新增的子产品和原先的子产品与其建立关系
        for (Long warehouseId : newWarehouseIds) {
            for (Long addId : addIdList) {
                //新增产品不存在分仓恢复的说法
                getProductWarehouseEntity(corpid, productId, warehouseNameMap, productMap,batchAddList, warehouseId, addId);
            }
            for (Long editId : editIdList) {
                if (unbundleMap.containsKey(editId + "_" + warehouseId)) {
                    rebundleList.add(unbundleMap.get(editId + "_" + warehouseId));
                    continue;
                }
                getProductWarehouseEntity(corpid, productId, warehouseNameMap, productMap, batchAddList, warehouseId, editId);
            }
        }
        // 不变的仓库需要新增的子产品与其建立关系
        for (Long warehouseId : copyWarehouseIds){
            for (Long addId : addIdList) {
                getProductWarehouseEntity(corpid, productId, warehouseNameMap, productMap, batchAddList, warehouseId, addId);
            }
        }
       /* // 不变的仓库需要删除的子产品与其删除关系
        List<ProductWarehouseEntity> wantDelChildList = new ArrayList<>();
        for (ProductWarehouseEntity productWarehouseEntity : productWarehouseList) {
            if (delIdList.contains(productWarehouseEntity.getProductId()) && copyWarehouseIds.contains(productWarehouseEntity.getWarehouseId())) {
                wantDelChildList.add(productWarehouseEntity);
            }
        }*/
        for (ProductWarehouseEntity productWarehouseEntity : batchAddList) {
            String key = productWarehouseEntity.getProductId() + StringConstant.CROSS + productWarehouseEntity.getWarehouseId();
            if (stockMap.containsKey(key)) {
                StockNotifyPojo stockNotifyPojo = stockMap.get(key);
                productWarehouseEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                productWarehouseEntity.setStockUpperLimit(stockNotifyPojo.getNum_4());
                productWarehouseEntity.setIsNotify(1);
            }
        }
        for (ProductWarehouseEntity productWarehouseEntity : rebundleList) {
            String key = productWarehouseEntity.getWarehouseKey();
            if (stockMap.containsKey(key)) {
                StockNotifyPojo stockNotifyPojo = stockMap.get(key);
                productWarehouseEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                productWarehouseEntity.setStockUpperLimit(stockNotifyPojo.getNum_4());
                productWarehouseEntity.setIsNotify(1);
            } else {
                productWarehouseEntity.setStockLowerLimit(0D);
                productWarehouseEntity.setStockUpperLimit(0D);
                productWarehouseEntity.setIsNotify(0);
            }
        }
        List<ProductWarehouseEntity> needUpdateNotifyWarehouseEntityList = new ArrayList<>();
        Map<String, ProductWarehouseEntity> oldWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductWarehouseEntity productWarehouseEntity : productWarehouseList) {
            String key = productWarehouseEntity.getProductId() + StringConstant.CROSS + productWarehouseEntity.getWarehouseId();
            oldWarehouseMap.put(key, productWarehouseEntity);
            ProductEntityExt productEntityExt = productMap.get(productWarehouseEntity.getProductId());
            if (Objects.nonNull(productEntityExt) && productEntityExt.getUpdateCost()) {
                productWarehouseEntity.setCost(productEntityExt.getData().getDouble(ProductEnum.COST.getAttr()));
            }
            if (Objects.equals(productWarehouseEntity.getIsNotify(), 1)) {
                if (!noPermissionWarehouseList.contains(productWarehouseEntity.getWarehouseId())) {
                    // 删除预警
                    productWarehouseEntity.setStockLowerLimit(0D);
                    productWarehouseEntity.setStockUpperLimit(0D);
                    productWarehouseEntity.setIsNotify(0);
                    // 更新预警
                    if (stockMap.containsKey(key)) {
                        StockNotifyPojo stockNotifyPojo = stockMap.get(key);
                        productWarehouseEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                        productWarehouseEntity.setStockUpperLimit(stockNotifyPojo.getNum_4());
                        productWarehouseEntity.setIsNotify(1);
                    }
                }
            } else {
                // 插入预警
                if (stockMap.containsKey(key)) {
                    StockNotifyPojo stockNotifyPojo = stockMap.get(key);
                    productWarehouseEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                    productWarehouseEntity.setStockUpperLimit(stockNotifyPojo.getNum_4());
                    productWarehouseEntity.setIsNotify(1);
                }
            }
            needUpdateNotifyWarehouseEntityList.add(productWarehouseEntity);
        }
        List<ProductWarehouseEntity> needUpdateSmartReplenishmentList = new ArrayList<>();
        // 全仓预警数据
        if (warehouseStockMap.containsKey(ProductConstant.ALL_WAREHOUSE_ID)) {
            List<StockNotifyPojo> stockNotifyPojos = warehouseStockMap.get(ProductConstant.ALL_WAREHOUSE_ID);
            for (StockNotifyPojo stockNotifyPojo : stockNotifyPojos) {
                if (!oldWarehouseMap.containsKey(stockNotifyPojo.getProductId() + StringConstant.CROSS + stockNotifyPojo.getWarehouseId())) {
                    ProductWarehouseEntity productWarehouseEntity = new ProductWarehouseEntity();
                    productWarehouseEntity.setCorpid(corpid);
                    productWarehouseEntity.setWarehouseId(stockNotifyPojo.getWarehouseId());
                    productWarehouseEntity.setParentId(productId);
                    productWarehouseEntity.setProductId(stockNotifyPojo.getProductId());
                    productWarehouseEntity.setWarehouseName(I18nMessageUtil.getMessage(ProductConstant.ALL_WAREHOUSE_NAME));
                    productWarehouseEntity.setIsNotify(1);
                    if (productMap.containsKey(stockNotifyPojo.getProductId())) {
                        productWarehouseEntity.setNum(productMap.get(stockNotifyPojo.getProductId()).getNum());
                        productWarehouseEntity.setCost(productMap.get(stockNotifyPojo.getProductId()).getData().getDouble(ProductEnum.COST.getAttr()));
                        if (Objects.equals(productWarehouseEntity.getNum(),0D)) {
                            productWarehouseEntity.setTotalCost(0D);
                        } else {
                            productWarehouseEntity.setTotalCost(Arith.mul(productWarehouseEntity.getNum(), productWarehouseEntity.getCost()));
                        }
                    } else {
                        productWarehouseEntity.setNum(0D);
                        productWarehouseEntity.setCost(0D);
                        productWarehouseEntity.setNum(0D);
                    }

                    productWarehouseEntity.setOriNum(0D);
                    productWarehouseEntity.setWarehouseChecked(1);
                    productWarehouseEntity.setWarehouseKey(productWarehouseEntity.getProductId() + "_" + productWarehouseEntity.getWarehouseId());
                    productWarehouseEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                    productWarehouseEntity.setStockUpperLimit(stockNotifyPojo.getNum_4());
                    batchAddList.add(productWarehouseEntity);
                }
                ProductWarehouseEntity podtWehusEntity = new ProductWarehouseEntity();
                podtWehusEntity.setCorpid(corpid);
                podtWehusEntity.setParentId(productId);
                podtWehusEntity.setProductId(stockNotifyPojo.getProductId());
                podtWehusEntity.setStockLowerLimit(stockNotifyPojo.getNum_3());
                needUpdateSmartReplenishmentList.add(podtWehusEntity);
            }
        }
        if (CollectionsUtil.isNotEmpty(needUpdateNotifyWarehouseEntityList)){
            needUpdateNotifyWarehouseEntityList.forEach(item ->{
                // 全仓预警需要更新的
                if(Objects.equals(ProductConstant.ALL_WAREHOUSE_ID,item.getWarehouseId())){
                    needUpdateSmartReplenishmentList.add(item);
                }
            });
        }
        List<Long> needUpdateProductIdList = new ArrayList<>();
        if(CollectionsUtil.isNotEmpty(needUpdateSmartReplenishmentList)){
            needUpdateSmartReplenishmentList.forEach(item -> needUpdateProductIdList.add(item.getProductId()));
            // 查询出需要更新的智能补货数据
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid,needUpdateProductIdList);
            Map<Long,SmartReplenishmentEntity> smartReplenishmentEntityMap = new HashMap<>();
            smartReplenishmentEntityList.forEach(item -> smartReplenishmentEntityMap.put(item.getProductId(),item));
            List<SmartReplenishmentEntity> updateList = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
                // 更新最低库存
                for (ProductWarehouseEntity productWarehouseEntity : needUpdateSmartReplenishmentList) {
                    Long entityId = productWarehouseEntity.getProductId();
                    if (smartReplenishmentEntityMap.containsKey(entityId)){
                        smartReplenishmentEntityMap.get(entityId).setMiniNum(productWarehouseEntity.getStockLowerLimit());
                        updateList.add(smartReplenishmentEntityMap.get(entityId));
                    }
                }
                smartReplenishmentModel.updateBatch(updateList,corpid);
            }
        }
        // 存在的仓库关系-库存预警数据
        if (CollectionsUtil.isNotEmpty(needUpdateNotifyWarehouseEntityList)) {
            productWarehouseModel.updateBatchNotifyMaybeCost(needUpdateNotifyWarehouseEntityList, corpid);
        }
        // 新增的仓库关系-库存预警数据
        if (CollectionsUtil.isNotEmpty(batchAddList)) {
            productWarehouseModel.insertBatch(batchAddList);
        }
        if (!rebundleList.isEmpty()) {
            productWarehouseModel.rebundleWarehouse(corpid,rebundleList);
        }
        // 删除仓库关系
        List<ProductWarehouseEntity> delWarehouseList = new ArrayList<>();
        delWarehouseList.addAll(wantDelWarehouseList);
       // delWarehouseList.addAll(wantDelChildList);
        if (!delWarehouseList.isEmpty()) {
//            productWarehouseModel.deleteByIdInAndParentId(corpid, delWarehouseList);
            productWarehouseModel.unbundleWarehouse(corpid,delWarehouseList);
            // 删除的全仓预警更新智能补货最低库存
            Map<Long,ProductWarehouseEntity> map = new HashMap<>(rebundleList.size());
            List<Long> productIdList = new ArrayList<>();
            // 如果需要解绑的仓库是全仓预警 则更新该产品的全仓预警为0
            delWarehouseList.forEach(item -> {
                if (Objects.equals(BasicConstant.ZERO,item.getWarehouseId())){
                    map.put(item.getProductId(),item);
                    productIdList.add(item.getProductId());
                }
            });
            // 查询出需要更新的智能补货数据
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid,needUpdateProductIdList);
            if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    smartReplenishmentEntity.setMiniNum(0D);
                    smartReplenishmentEntity.setUpdateTime(DateTimeUtil.getInt());
                }
                smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
            }

        }
        Set<Long> existWarehouseIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        existWarehouseIds.addAll(newWarehouseIds);
        existWarehouseIds.addAll(copyWarehouseIds);
        return existWarehouseIds;
    }

    public void getProductWarehouseEntity(String corpid, Long productId, Map<Long, String> warehouseNameMap, Map<Long, ProductEntityExt> productMap, List<ProductWarehouseEntity> batchAddList, Long warehouseId, Long addId) {
        ProductWarehouseEntity productWarehouseEntity = new ProductWarehouseEntity(0, 0D, 0D);
        productWarehouseEntity.setCorpid(corpid);
        productWarehouseEntity.setWarehouseId(warehouseId);
        productWarehouseEntity.setParentId(productId);
        productWarehouseEntity.setProductId(addId);
        productWarehouseEntity.setWarehouseName(warehouseNameMap.getOrDefault(warehouseId, ""));
        productWarehouseEntity.setNum(0D);
        productWarehouseEntity.setOriNum(0D);
        productWarehouseEntity.setWarehouseChecked(1);
        productWarehouseEntity.setCost(productMap.get(addId).getData().getDouble(ProductEnum.COST.getAttr()));
        productWarehouseEntity.setTotalCost(0D);
        productWarehouseEntity.setWarehouseKey(addId + "_" + warehouseId);
        batchAddList.add(productWarehouseEntity);
    }


    @Override
    public Object getPriceBySummary(List<PaasFormDataEntityExt> childProductESList, String corpid, Long formDataId) throws XbbException {
        if (childProductESList.isEmpty()) {
            childProductESList = getDataByParentId(corpid, formDataId);
        }
        if (childProductESList.isEmpty()) {
            return "";
        }
        PaasFormDataEntityExt paasFormDataEsEntity = childProductESList.get(0);
        PaasFormExplainEntity productExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(productExplainEntity.getExplains());
        FieldAttrEntity priceAttrEntity = explainMap.get(ProductEnum.PRICE.getAttr());
        String price4Show;
        if (!childProductESList.isEmpty()) {
            // 是否是多单位
            boolean enableMultiUnit = Objects.equals(childProductESList.get(0).getData().getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE);
            List<PaasFormDataEntityExt> multiProductList = new ArrayList<>();
            Map<Long, Object> multiProductsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (enableMultiUnit) {
                Long parentId = childProductESList.get(0).getData().getLong(ProductEnum.PARENT_ID.getAttr());
                handleMultiPrice(multiProductsMap, multiProductList,corpid, parentId, priceAttrEntity.getAccuracy());
            }

            if (childProductESList.size() > 1) {
                if (enableMultiUnit) {
                    price4Show = getPriceOrCostRegion(multiProductList, ProductEnum.PRICE.getAttr(), priceAttrEntity.getAccuracy());
                }else {
                    Double min = getDoubleOrDefaultFromFormData(childProductESList.get(0).getData(), ProductEnum.PRICE.getAttr(), 0D);
                    Double max = getDoubleOrDefaultFromFormData(childProductESList.get(childProductESList.size() - 1).getData(), ProductEnum.PRICE.getAttr(), 0D);
                    if (Objects.equals(Double.compare(min, max), 0)) {
                        price4Show = AttrDecimalPrecisionHelper.parseThousandth(min, priceAttrEntity.getAccuracy()).toString();
                    } else {
                        price4Show = String.format(StringConstant.PRICE_RANFE, AttrDecimalPrecisionHelper.parseThousandth(min, priceAttrEntity.getAccuracy()), AttrDecimalPrecisionHelper.parseThousandth(max, priceAttrEntity.getAccuracy()));
                    }
                }
            } else {
                JSONObject childProductObj = paasFormDataEsEntity.getData();
                String price = FastJsonHelper.getStringOrDefaultFromFormData(childProductObj, ProductEnum.PRICE.getAttr(), "");
                if (enableMultiUnit) {
                    price4Show = getPriceOrCostRegion(multiProductList, ProductEnum.PRICE.getAttr(), priceAttrEntity.getAccuracy());
                }else {
                    price4Show = AttrDecimalPrecisionHelper.parseThousandth(Double.parseDouble(price), priceAttrEntity.getAccuracy()).toString();
                }
            }
            return price4Show;
        }
        return "";
    }

    @Override
    public XbbAggregatedPage<PaasFormDataEntity> productEntityByProductId(Set<Long> productIdSet, String corpid, String nameOrNoLike,
                                                                       Integer page, Integer pageSize, String platForm) throws XbbException {
        Integer del = DelEnum.NORMAL.getDel();
        //查询产品
        BoolQueryBuilder productQuery = boolQuery();
        productQuery.filter(termQuery("corpid.keyword", corpid));
        productQuery.filter(termQuery("del", del));
        productQuery.filter(termsQuery("flowStatus", FlowStatusEnum.getStatisticType()));
        productQuery.filter(termsQuery("dataId", productIdSet));
        String nameField = ProductEnum.getAttrConnectData(ProductEnum.NAME);
        String numberField = ProductEnum.getAttrConnectData(ProductEnum.PRODUCT_NO);
        String nameAttr = ProductEnum.getAttrConnectData(ProductEnum.NAME);
        String numberAttr = ProductEnum.getAttrConnectData(ProductEnum.PRODUCT_NO);
        //产品名称或编号模糊查询
        if (StringUtil.isNotEmpty(nameOrNoLike)) {
            QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(nameField, nameOrNoLike);
            QueryBuilder productNoQuery = QueryBuilders.matchPhraseQuery(numberField, nameOrNoLike);
            productQuery.should(queryBuilder);
            productQuery.should(productNoQuery);
            productQuery.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
        }
        //需要查出的字段
        List<String> productFields = Arrays.asList("dataId", nameAttr, numberAttr);
        return esHelper.findByPage(IndexTypeEnum.IDX_SAAS_PRODUCT, productQuery, PaasFormDataEntity.class, productFields, page, pageSize, null);
    }

    @Override
    public List<ProductSearchDetailVO> productSearchFormat(List<PaasFormDataEntity> productList) {
        List<ProductSearchDetailVO> productSearchDetailVOS = new ArrayList<>();
        for (PaasFormDataEntity entity : productList) {
            JSONObject data = entity.getData();
            Long id = entity.getDataId();
            String name = data.getString(ProductEnum.NAME.getAttr());
            String productNo = data.getString(ProductEnum.PRODUCT_NO.getAttr());
            ProductSearchDetailVO productSearchDetailVO = new ProductSearchDetailVO();
            StringBuilder productInfo = new StringBuilder();
            if (StringUtil.isEmpty(name)) {
                continue;
            } else {
                productInfo.append(name);
            }
            if (!StringUtil.isEmpty(productNo)) {
                productInfo.append("(").append(productNo).append(")");
            }
            productSearchDetailVO.setProductId(String.valueOf(id));
            productSearchDetailVO.setProductInfo(String.valueOf(productInfo));
            productSearchDetailVOS.add(productSearchDetailVO);
        }
        return productSearchDetailVOS;
    }

    @Override
    public List<PaasFormDataEntityExt> getDataByParentId(String corpid, Long formDataId) throws XbbException {
        EsDataDTO esDataDTO = new EsDataDTO();
        esDataDTO.setCorpid(corpid);
        esDataDTO.setDel(0);
        esDataDTO.setBusinessType(XbbRefTypeEnum.PRODUCT.getCode());
        esDataDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        esDataDTO.setFieldList(null);
        esDataDTO.setPageSize(10000);
        Map<String, String> sortMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        sortMap.put("field", ProductEnum.PRICE.getAttr());
        sortMap.put("sort", "asc");
        esDataDTO.setSortMap(sortMap);
        List<ConditionsEntityExt> conditionsEntityExtList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        conditionsEntityExtList.add(EsUtil.packageContions(ProductEnum.PARENT_ID.getAttr(),
                Collections.singletonList(formDataId), ConditionEnum.EQUAL, ProductEnum.PARENT_ID.getFieldType()));
        esDataDTO.setConditionsEntityExtList(conditionsEntityExtList);
        PaasFormDataEsListVO esDataList = paasFormDataService.getEsDataList(esDataDTO);
        List<PaasFormDataEntityExt> childProductESList = esDataList.getPaasFormDataESList();
        return childProductESList;
    }


    /**
     * 产品名称或编号模糊查询（查出产品id、产品名称和父产品id）
     *
     * @param productSearchDTO corpid, nameOrNoLike
     * @return java.util.List<com.xbongbong.paas.domain.entity.PaasFormDataEntityExt>
     * @author 徐俊杰
     * @date 2019/4/11 9:09
     * @since v1.0
     */
    private XbbAggregatedPage<PaasFormDataEntity> listOfSelectProduct(ProductSearchDTO productSearchDTO) throws XbbException {
        //分页信息
        Integer page = productSearchDTO.getPage();
        Integer pageSize = productSearchDTO.getPageSize();
        //平台区分每页数量,仅当前端没有传值时会置入默认值
        String platForm = productSearchDTO.getPlatform();
        if (Objects.equals(platForm, PlatFormEnum.DINGTALK.getValue()) && pageSize == null) {
            pageSize = PageConstant.DEFAULT_PAGE_SIZE;
        } else if (Objects.equals(platForm, PlatFormEnum.WEB.getValue()) && pageSize == null) {
            pageSize = PageConstant.DEFAULT_PAGE_SIZE_SMALL;
        }
        productSearchDTO.setPageSize(pageSize);
        //查询信息
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //基础参数
        boolQueryBuilder.filter(termQuery("corpid.keyword", productSearchDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        String parentIdData = ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID);
        boolQueryBuilder.mustNot(termQuery(parentIdData, 0));
        //产品名称
        String nameAttr = ProductEnum.NAME.getAttr();
        String nameField = "data." + nameAttr;
        //产品编号
        String productNoAttr = ProductEnum.PRODUCT_NO.getAttr();
        String productNoField = "data." + productNoAttr;
        String nameOrNoLike = productSearchDTO.getNameOrNoLike();
        //产品名称或编号模糊查询
        if (StringUtil.isNotEmpty(nameOrNoLike)) {
            QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(nameField, nameOrNoLike);
            QueryBuilder productNoQuery = QueryBuilders.matchPhraseQuery(productNoField, nameOrNoLike);
            boolQueryBuilder.should(queryBuilder);
            boolQueryBuilder.should(productNoQuery);
            boolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
        }
        //需要查出的字段
        List<String> fieldList = Arrays.asList("dataId", nameField, productNoField);
        //TODO 做成分页查询
        return esHelper.findByPage(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList, page, pageSize, null);
    }

    private JSONObject getByKey(JSONArray specArray, String key) {
        JSONObject object = new JSONObject();
        object.put("name", key);
        object.put("value", new JSONArray());
        if (specArray.isEmpty()) {
            specArray.add(object);
            return object;
        }
        for (int i=0; i<specArray.size(); i++) {
            JSONObject specItem = specArray.getJSONObject(i);
            if (specItem.getString("name").equals(key)) {
                return specItem;
            }
        }
        specArray.add(object);
        return object;
    }


    @Override
    public void setProductSupplierAndWarehouse(PaasFormDataEsListVO formDataListVO, String corpid, List<Long> dataIdList, boolean isSpuList) throws XbbException {
        Map<Long, List<SupplierProductEntity>> supplierMap = supplierProductModel.getSupplierProductByParentIdIn(corpid, dataIdList,isSpuList);
        List<String> fieldList = new ArrayList<>();
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(ParameterConstant.WAREHOUSE_ID));
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("warehouseName"));
        fieldList.add(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(StringConstant.PARENTID));
        Map<Long, List<ProductWarehouseEntity>> warehouseMap = productWarehouseModel.getWarehouseProductMapByParentIdIn(corpid, dataIdList, fieldList);
        for (PaasFormDataEntityExt paasFormDataEntityExt : formDataListVO.getPaasFormDataESList()) {
            Long parentId = isSpuList ? paasFormDataEntityExt.getId() : Math.round(paasFormDataEntityExt.getData().getDouble(ProductEnum.PARENT_ID.getAttr()));
            List<SupplierProductEntity> supplierProductEntityList = supplierMap.get(paasFormDataEntityExt.getDataId());
            JSONArray supplierArr = new JSONArray();
            Map<Long, String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionUtils.isNotEmpty(supplierProductEntityList)) {
                for (SupplierProductEntity supplierProductEntity : supplierProductEntityList) {
                    supplierNameMap.put(supplierProductEntity.getSupplierId(), supplierProductEntity.getSupplierName());
                }
                for (Map.Entry<Long, String> entry : supplierNameMap.entrySet()) {
                    JSONObject supplierObj = new JSONObject();
                    supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, entry.getKey());
                    supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, entry.getValue());
                    supplierObj.put(StringConstant.BUSINESS_TYPE, XbbRefTypeEnum.SUPPLIER.getCode());
                    supplierObj.put("subBusinessType", XbbRefTypeEnum.SUPPLIER.getCode());
                    supplierObj.put(StringConstant.SAAS_MARK, SaasMarkEnum.SAAS.getCode());
                    supplierArr.add(supplierObj);
                }
            }
            paasFormDataEntityExt.getData().put(ProductEnum.SUPPLIER.getAttr(), supplierArr);
            List<ProductWarehouseEntity> warehouseEntityList = warehouseMap.get(parentId);
            JSONArray warehouseArr = new JSONArray();
            if (CollectionUtils.isNotEmpty(warehouseEntityList)) {
                Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (ProductWarehouseEntity productWarehouseEntity : warehouseEntityList) {
                    warehouseNameMap.put(productWarehouseEntity.getWarehouseId(), productWarehouseEntity.getWarehouseName());
                }
                warehouseNameMap.remove(ProductConstant.ALL_WAREHOUSE_ID);
                for (Map.Entry<Long, String> entry : warehouseNameMap.entrySet()) {
                    JSONObject warehouseObj = new JSONObject();
                    warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, entry.getKey());
                    warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, entry.getValue());
                    warehouseObj.put(StringConstant.BUSINESS_TYPE, XbbRefTypeEnum.WAREHOUSE.getCode());
                    warehouseObj.put("subBusinessType", XbbRefTypeEnum.WAREHOUSE.getCode());
                    warehouseObj.put(StringConstant.SAAS_MARK, SaasMarkEnum.SAAS.getCode());
                    warehouseArr.add(warehouseObj);
                }
            }
            paasFormDataEntityExt.getData().put(ProductEnum.WAREHOUSE.getAttr(), warehouseArr);
        }
    }

    @Override
    public void setProductSupplier(PaasFormDataEsListVO formDataListVO, String corpid, List<Long> dataIdList) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("productIdIn", dataIdList);
        List<SupplierProductEntity> supplierProductEntities = supplierProductModel.findEntitys(param);
        Map<Long, List<SupplierProductEntity>> supplierMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (SupplierProductEntity supplierProductEntity : supplierProductEntities) {
            List<SupplierProductEntity> list = new ArrayList<>();
            if (supplierMap.containsKey(supplierProductEntity.getProductId()))  {
                list = supplierMap.get(supplierProductEntity.getProductId());
            }
            list.add(supplierProductEntity);
            supplierMap.put(supplierProductEntity.getProductId(), list);
        }
        for (PaasFormDataEntityExt paasFormDataEntityExt : formDataListVO.getPaasFormDataESList()) {
            List<SupplierProductEntity> supplierProductEntityList = supplierMap.get(paasFormDataEntityExt.getId());
            JSONArray supplierArr = new JSONArray();
            Map<Long, String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionUtils.isNotEmpty(supplierProductEntityList)) {
                for (SupplierProductEntity supplierProductEntity : supplierProductEntityList) {
                    supplierNameMap.put(supplierProductEntity.getSupplierId(), supplierProductEntity.getSupplierName());
                }
                for (Map.Entry<Long, String> entry : supplierNameMap.entrySet()) {
                    JSONObject supplierObj = new JSONObject();
                    supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, entry.getKey());
                    supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, entry.getValue());
                    supplierObj.put(StringConstant.BUSINESS_TYPE, XbbRefTypeEnum.SUPPLIER.getCode());
                    supplierObj.put("subBusinessType", XbbRefTypeEnum.SUPPLIER.getCode());
                    supplierObj.put(StringConstant.SAAS_MARK, SaasMarkEnum.SAAS.getCode());
                    supplierArr.add(supplierObj);
                }
            }
            paasFormDataEntityExt.getData().put(ProductEnum.SUPPLIER.getAttr(), supplierArr);
        }
    }

    @Override
    public List<StockNotifyPojo> getSaveParam(JSONObject dataList, Map<Long, String> supplierNameMap, Map<Long, String> warehouseNameMap) throws XbbException{
        List<StockNotifyPojo> stockNotifyList = new ArrayList<>();
        if (Objects.equals(dataList.getInteger(ProductEnum.IS_NOTIFY.getAttr()), 1)) {
            stockNotifyList = dataList.getJSONArray(ProductEnum.STOCK_NOTIFY.getAttr()).toJavaList(StockNotifyPojo.class);
        }
        JSONArray supplierArr = dataList.getJSONArray(ProductEnum.SUPPLIER.getAttr());
        if (supplierArr != null && !supplierArr.isEmpty()) {
            for (int i = 0; i < supplierArr.size(); i++) {
                JSONObject jsonObject = supplierArr.getJSONObject(i);
                supplierNameMap.put(jsonObject.getLong(StringConstant.SAAS_LINK_BUSINESS_ID), jsonObject.getString(StringConstant.SAAS_LINK_BUSINESS_NAME));
            }
        }
        JSONArray warehouseArr = dataList.getJSONArray(ProductEnum.WAREHOUSE.getAttr());
        if (warehouseArr != null && !warehouseArr.isEmpty()) {
            for (int i = 0; i < warehouseArr.size(); i++) {
                JSONObject jsonObject = warehouseArr.getJSONObject(i);
                warehouseNameMap.put(jsonObject.getLong(StringConstant.SAAS_LINK_BUSINESS_ID), jsonObject.getString(StringConstant.SAAS_LINK_BUSINESS_NAME));
            }
        }
        return stockNotifyList;
    }


    /**
     * 修改产品详情页供应商名称
     * @param corpid 公司id
     * @param supplierId 数据id
     * @param supplierName 供应商名称
     * @return void
     * @throws XbbException 业务异常
     */
    @Override
    public void dataConsistencyUpdateSupplier(String corpid, Long supplierId, String supplierName) throws XbbException {
        try {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("supplierId", supplierId);
            List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.findEntitys(param);

            Set<Long> ids = new HashSet<>();

            List<SupplierProductEntity> updateBatchList = new ArrayList<>();
            for (SupplierProductEntity supplierProductEntity : supplierProductEntityList) {
                supplierProductEntity.setSupplierName(supplierName);
                updateBatchList.add(supplierProductEntity);
                ids.add(supplierProductEntity.getProductId());
            }
            ////更新供应商产品表
            if (!updateBatchList.isEmpty()){
                supplierProductModel.updateBatch(updateBatchList, corpid);
            }
            Map<String, Object> param1 = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param1.put("corpid", corpid);
            param1.put("idIn", ids);
            param1.put("del", 0);
            List<ProductEntityExt> productList = productModel.findEntitys(param1);
            if (Objects.nonNull(productList) && !productList.isEmpty()) {
                List<ProductUpdateDTO> productUpdateDTOList = new ArrayList<>();
                for (ProductEntityExt entityExt : productList) {
                    JSONObject data = entityExt.getData();
                    //供应商ID 数组
                    JSONArray supplierIdArray = (JSONArray)data.get(ProductEnum.SUPPLIER.getAttr());
                    //供应商名称数组
                    JSONArray supplierNameArray = (JSONArray)data.get(ProductEnum.SUPPLIER_LINK_TEXT.getAttr());
                    //定义下标
                    Integer index = null;
                    for (int i = 0; i < supplierIdArray.size(); i++) {
                        if (Objects.equals(supplierIdArray.get(i), supplierId)){
                        index = i;
                        break;
                        }
                    }
                    if (Objects.nonNull(index)){
                        supplierNameArray.set(index, supplierName);
                    }
                    data.put(ProductEnum.SUPPLIER_LINK_TEXT.getAttr(),supplierNameArray);
                    ProductUpdateDTO productUpdateDTO = new ProductUpdateDTO();
                    productUpdateDTO.setId(entityExt.getId());
                    productUpdateDTO.setData(data);
                    productUpdateDTOList.add(productUpdateDTO);
                }
                ProductUpdateBatchDTO productUpdateBatchDTO = new ProductUpdateBatchDTO();
                productUpdateBatchDTO.setCorpid(corpid);
                productUpdateBatchDTO.setProductList(productUpdateDTOList);
                //更新产品表
                updateAttrBatch(productUpdateBatchDTO);

            }
        } catch (Exception e){
            LOG.error("ProductServiceImpl.dataConsistencyUpdateSupplier 出错，corpid=" + corpid + "  supplierId=" + supplierId + " supplierName=" + supplierName, e);
        }

    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        ProductUpdateBatchDTO productUpdateBatchDTO = new ProductUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, productUpdateBatchDTO);
        List<ProductUpdateDTO> productList = new ArrayList<>();
        addBatchList.forEach(item ->{
            ProductUpdateDTO productUpdateDTO= new ProductUpdateDTO();
            productUpdateDTO.setData(item.getData());
            productUpdateDTO.setId(item.getId());
            productList.add(productUpdateDTO);
        });
        productUpdateBatchDTO.setProductList(productList);
        updateBatch(productUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存产品负责人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            productUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存产品负责人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            productUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    private ProductUpdateBatchVO updateAttrBatch(ProductUpdateBatchDTO productUpdateBatchDTO) throws  XbbException {
        ProductUpdateBatchVO productUpdateBatchVO = new ProductUpdateBatchVO();
        try {
            String corpid = productUpdateBatchDTO.getCorpid();
            List<ProductUpdateDTO> productList = productUpdateBatchDTO.getProductList();
            if (Objects.nonNull(productList) && !productList.isEmpty()){
                List<UpdateDataEntity> list = new ArrayList<>();
                productList.forEach((item) -> {
                    list.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
                if(!list.isEmpty()){
                    productModel.updateBatch(list, corpid);
                }
            }
        }catch (Exception e){
            LOG.error("ProductServiceImpl.updateAttrBatch 批量更新出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productUpdateBatchVO;
    }


    @Override
    public void updateProductStock(Map<Long, ProductStockUpdateEntity> productAddMap, String corpid) throws XbbException {
        workflowProductHelp.updateProductStock(productAddMap, corpid);
    }

    @Override
    public ProductSerialVO repeat(ProductSerialDTO productSerialDTO) throws XbbException {
        ProductSerialVO productSerialVO = new ProductSerialVO();
        String corpid = productSerialDTO.getCorpid();
        Long productId = productSerialDTO.getProductId();
        List<String> serialNumber = productSerialDTO.getSerialNumber();
        if (CollectionUtils.isEmpty(serialNumber)) {
            return productSerialVO;
        }
        for (String seq : serialNumber) {
            if (StringUtils.isEmpty(seq)) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205091);
            }
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("productId", productId);
        param.put(ParameterConstant.CORPID, corpid);
        param.put("seqIn", serialNumber);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());

        List<ProductSerialBalanceEntity> entitys = productSerialBalanceModel.findEntitys(param);
        if (CollectionUtils.isNotEmpty(entitys)) {
            List<String> serialList = new ArrayList<>();
            entitys.forEach(item -> serialList.add(item.getSeq()));
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205071, String.format(ProductErrorCodeEnum.API_ERROR_205071.getMsg(), serialList.toString()));
        }

        return productSerialVO;
    }

    @Override
    public ProductSearchVO checkStock(ProductStockVerifyDTO productSearchDTO) throws XbbException {
        ProductSearchVO productSearchVO = new ProductSearchVO();
        if (!Objects.equals(productSearchDTO.getBusinessType(), XbbRefTypeEnum.PRODUCT.getCode())) {
            return productSearchVO;
        }
        productSearchVO.setIsZero(true);
        Long productId = productSearchDTO.getDataId();
        String corpid = productSearchDTO.getCorpid();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID),productId));
        BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
        innerBoolQueryBuilder.should(rangeQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.STOCK)).lt(0));
        innerBoolQueryBuilder.should(rangeQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.STOCK)).gt(0));
        innerBoolQueryBuilder.minimumShouldMatch(1);
        boolQueryBuilder.filter(innerBoolQueryBuilder);
        List<ProductEntityExt> list = paasEsModel.getDataList(boolQueryBuilder, IndexTypeEnum.IDX_SAAS_PRODUCT,
                Arrays.asList( ProductEnum.STOCK.getAttr()), 1, 1, ProductEntityExt.class, null, null);
        if (CollectionsUtil.isNotEmpty(list)) {
            productSearchVO.setIsZero(false);
        }
        return productSearchVO;
    }

    @Override
    public boolean hasBatchOrSeqProduct(CompanyConfigEnum companyConfigEnum, String corpid) throws XbbException{
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        if (Objects.equals(companyConfigEnum, CompanyConfigEnum.ENABLE_BATCH_SHELF_MANAGEMENT)) {
            boolQueryBuilder.filter(termQuery(ProductEnum.getAttrConnectData(ProductEnum.ENABLE_BATCH_SHELF_LIFE), BasicConstant.IS_USE));
        } else if (Objects.equals(companyConfigEnum, CompanyConfigEnum.ENABLE_SEQ_MANAGEMENT)) {
            boolQueryBuilder.filter(termQuery(ProductEnum.getAttrConnectData(ProductEnum.ENABLE_SERIAL_NUMBER), BasicConstant.IS_USE));
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCT.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT.getIndex());
        searchRequest.source(sourceBuilder);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 1);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        if (esEntities == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        List<PaasFormDataEntityExt> resultList = new ArrayList<>(esEntities.getContent());
        return CollectionsUtil.isNotEmpty(resultList);
    }

    @Override
    public void formatBatchExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        List<String> batchFieldList = Arrays.asList(ProductEnum.BATCH_SHELF_LIFE_MANAGEMENT.getAttr(), ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr(),
                ProductEnum.SHELF_LIFE_DAYS.getAttr(), ProductEnum.EXPIRATION_ALERT_DAYS.getAttr());
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
            if (batchFieldList.contains(fieldAttrEntity.getAttr())) {
                BatchSeqExplainHelp.getInstance().formatExplain4BatchSeqAffectNormalAttr(enable, fieldAttrEntity);
            }
        }
    }

    @Override
    public void formatSeqExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        List<String> seqFieldList = Arrays.asList(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr(), ProductEnum.SERIAL_NUMBER_MANAGEMENT.getAttr());
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
            if (seqFieldList.contains(fieldAttrEntity.getAttr())) {
                BatchSeqExplainHelp.getInstance().formatExplain4BatchSeqAffectNormalAttr(enable, fieldAttrEntity);
            }
        }
    }

    @Override
    public void formatBatchOrSeqExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable, String alias) {
        if (Objects.equals(CompanyConfigEnum.ENABLE_BATCH_SHELF_MANAGEMENT.getAlias(), alias)) {
            formatBatchExplain(fieldAttrEntityList, enable);
        } else if (CompanyConfigEnum.ENABLE_SEQ_MANAGEMENT.getAlias().equals(alias)) {
            formatSeqExplain(fieldAttrEntityList, enable);
        }
    }

    /**
     * 通过id列表获取产品
     *
     * @param corpid      公司id
     * @param productIdIn 产品id列表
     * @param del         删除标志
     * @param fieldList
     * @author long.rao
     * @date 2019-08-16 13:51
     */
    @Override
    public List<PaasFormDataEntityExt> getProductListByIds(String corpid, List<Long> productIdIn, Integer del, List<String> fieldList) throws XbbException{
        if (productIdIn == null || productIdIn.isEmpty()) {
            return new ArrayList<>();
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termsQuery("dataId", productIdIn));
        if (del != null) {
            boolQueryBuilder.filter(termQuery("del", del));
        }
        XbbAggregatedPage<PaasFormDataEntityExt> byPage = esHelper.findByPage(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, ProductEntityExt.class, fieldList, 0, productIdIn.size(), null);
        return byPage.getContent();
    }

    @Override
    public void updateProductCostByid(List<ProductEntityExt> productEntityExtList, String corpid) throws XbbException {
        if(CollectionsUtil.isEmpty(productEntityExtList)){
            return;
        }
        productModel.updateProductCostByid(productEntityExtList, corpid);
        List<UpdateDataEntity> list = new ArrayList<>();
        productEntityExtList.forEach(productEntityExt -> {
            UpdateDataEntity updateDataEntity = new UpdateDataEntity();
            updateDataEntity.setId(productEntityExt.getId());
            updateDataEntity.setCorpid(corpid);
            List<UpdateDataValueEntity> data = new ArrayList<>();
            UpdateDataValueEntity updateDataValueEntity1 = new UpdateDataValueEntity();
            updateDataValueEntity1.setKey(ProductEnum.COST.getAttr());
            updateDataValueEntity1.setEsKey(ProductEnum.COST.getAttr());
            updateDataValueEntity1.setValue(productEntityExt.getCost());
            data.add(updateDataValueEntity1);
            UpdateDataValueEntity updateDataValueEntity2 = new UpdateDataValueEntity();
            updateDataValueEntity2.setKey(ProductEnum.STOCK.getAttr());
            updateDataValueEntity2.setEsKey(ProductEnum.STOCK.getAttr());
            updateDataValueEntity2.setValue(productEntityExt.getNum());
            data.add(updateDataValueEntity2);
            updateDataEntity.setData(data);
            list.add(updateDataEntity);
        });
        paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_SAAS_PRODUCT);
    }

    @Override
    public void formatWaitOutstockProductExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO) {
        for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList){
            JSONObject data = paasFormDataEntityExt.getData();
            //处理产品名称
            String productName = data.getJSONArray(WaitOutstockEnum.PRODUCT_NAME.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitOutstockEnum.PRODUCT_NAME.getAttr(),productName);
            //处理产品编号
            String productNo = data.getJSONArray(WaitOutstockEnum.PRODUCT_NO.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitOutstockEnum.PRODUCT_NO.getAttr(),productNo);
            //处理合同名称
            String purchaseName = data.getJSONArray(WaitOutstockEnum.NAME.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitOutstockEnum.NAME.getAttr(),purchaseName);
            //处理合同编号
            String purchaseNo = data.getJSONArray(WaitOutstockEnum.CONTRACT_NO.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitOutstockEnum.CONTRACT_NO.getAttr(),purchaseNo);
            //处理客户名称
            String supplier = data.getJSONArray(WaitOutstockEnum.LINK_CUSTOMER.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitOutstockEnum.LINK_CUSTOMER.getAttr(),supplier);
            //处理时间格式
            String addTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitOutstockEnum.ADD_TIME.getAttr()), DateTimeUtil.SDF);
            String updateTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitOutstockEnum.UPDATE_TIME.getAttr()), DateTimeUtil.SDF);
            String signTime = "";
            if (Objects.nonNull(data.get(WaitOutstockEnum.SIGN_TIME.getAttr()))) {
                if (data.get(WaitOutstockEnum.SIGN_TIME.getAttr()) instanceof Number) {
                    signTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitOutstockEnum.SIGN_TIME.getAttr()), DateTimeUtil.SDFDate);
                }
            }
            data.put(ContractEnum.ADD_TIME.getAttr(),addTime);
            data.put(ContractEnum.UPDATE_TIME.getAttr(),updateTime);
            data.put(ContractEnum.SIGN_TIME.getAttr(),signTime);

        }
    }
}
